0
\$\begingroup\$

Background

I am testing out a "Pause" system for my game. I have a Game Manager script and figured as it's the GM, it's a good place to stick a Pause system.

My pause works that on pressing "P" key, the timeScale is switched between 0 and 1. Due to the nature of the game, if the game is paused and then unpaused I want the timeScale to not "jump" to 1 but to gradually increase, taking half a second to reach "normal" game speed again.

This aspect is NOT my issue. This is just background.

My Code:

I have the pause detection in the Update script. I figured two if statements to check Timescale values and then to take appropriate action.

(SloMoTime is a timescale that kicks in when the player wins or looses the level)

My Code:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GManager : MonoBehaviour
{
    public float sloMoTime = 0.2f;
    public bool ballInPlay = false;

    ....

 void Update()
     {
     if(Input.GetButtonDown("PauseGame") && ballInPlay == true)
     {
         if (Time.timeScale == 0)
            {
            //Game is already paused, so now continue...
            // dactivate "paused" text notice
            paused.SetActive(false);
            /***
             * Becauase we are speeding time up we can't use deltaTime
             * Easy as the timescale we want is 0.5f so 1/0.5 == 2. So use 2.  
             ***/
            Time.timeScale = Mathf.MoveTowards(Time.timeScale, 1.0f, 2f);
            }
        if (Time.timeScale > slowMoTime)
            {
            //Pause the game.
            Time.timeScale = 0;
            // Show "paused" Text notice.
            paused.SetActive(true);
            }
        }
    } //end Update. 
} //close class.

Now, Can you see any major issues here?

My Issue

I found running my script from above, that the game did not pause.

I expected every frame to load Update, then to check IF number 1, and then check If number 2 (hence in that order). then continue.

I found using error logs that by swapping the If statments around that only the first if statement was ever executed. So the game would alternatively always pause but then never unpause. I additionally found with error logs that the values of TimeScale where not causing this inconsistency.

What I have trouble with is understanding why this happens. Why do two completely mutually exclusive IF statements not both fire, when in the same method?

FAILS:

Class {
    void Update () {
       if(){
          //works
       }

       if(){
         //never works
       }
   } //close method.
} 

A Solution

BUT putting the second IF statement within an else solves this issue.

WORKS:

Class {
    void Update() {
       if(){
          //works
       }
       else if(){
         //works
       }
   } //close method.
} 

Obviously this is impractical for more than a few ifs at once and I find it hard to understand why this logic works and the previous logic never did.

I havn't yet dug into if this is Update or timeScale (entity rather than value) specific but Why does this happen?

\$\endgroup\$
2
\$\begingroup\$

A few things:

  • Altering the timescale inside a conditional that requires the timescale to be zero only works on the first Update. (And using == 0 is a bad practice for floats anyway).
  • Due to point one, your code does this:
    1. Update
      1. Time.timeScale == 0 = false
      2. Time.timeScale > slowMoTime == true
        • Set timescale to 0
    2. Update
      1. Time.timeScale == 0 = true
        • Set timescale to slightly more than 0
      2. Time.timeScale > slowMoTime == false
    3. Update
      1. Time.timeScale == 0 = false
      2. Time.timeScale > slowMoTime == false
    4. Update
      1. Both are false forever.

So, your game is actually unpausing, it's just moving very, very slowly. You should use boolean flags to determine the state you want to be in, instead of relying on the state of the thing you're actively changing.

Further, you wouldn't want this in the update like it is. Even if this was working as you expected, it would just toggle back and forth between paused and unpaused.

And, with your update, Input.GetButtonDown is only going to trigger the very first frame you press the button. So, you can take the steps above and everytime it says Update, is the same as you pressing the pause key once.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the feedback. however I swapped the if ordering so the "to pause" (second if) if was put first and that paused ok, but then wouldn't unpause. Why would the button press not trigger in future updates? \$\endgroup\$ – Martin Nov 29 '16 at 22:03
  • \$\begingroup\$ Would you suggest a better place to sit this action to occur on pressing "P"? I agree in principle about using boolean flags, however I see that if the timeScale is 0 < Time.timeScale< sloMoTime then it will be speeding up and wouldn't be paused as it was paused at most 0.1 (0.5/5) seconds beforehand. \$\endgroup\$ – Martin Nov 29 '16 at 22:06
  • \$\begingroup\$ If it's swapped, it can still get into the state where neither condition is true. Mostly because of trying to Lerp the timescale inside a conditional that requires the conditional to be zero, change that first. Instead of boolean flags, create a simple state machine using an enum or even a string with a state. \$\endgroup\$ – MichaelHouse Nov 29 '16 at 22:19
  • \$\begingroup\$ Thank you for the advise and the help, but the original mystery is that the original if statements both work correctly when the second is put in an else statement. I can't seem to understand that logic process. And in reference to the "game was unpausing but moving very slowly" I could tell the game wasn't unpausing because the "pause" text was still active, showing that that if hadn't returned true. \$\endgroup\$ – Martin Nov 29 '16 at 22:22
  • \$\begingroup\$ @Martin It's the Mathf.MoveTowards method. I was wrong, it's not really tiny, it's big. It gets set to 1 right away. So the next statement pauses the game again, in the same frame. The third parameter is the maximum delta, with a delta of 2, it gets to 1 the first time. \$\endgroup\$ – MichaelHouse Nov 29 '16 at 22:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.