Pause using Timescale=0

Hello, i read some tutorials about pausing menu, and they use the “trick” of setting Timescale =0f; so all the physics and movement seem paused.

Reading further, i know that some coroutines and some things are not paused, so its not a “full pause”.

Is this a correct way to implement pause ? Its a better way for “full freeze/full pause” ?

Thanks in advance

There’s not one single way to pause a game.

In my current project I first used timescale=0 when showing the menu but then decided it was much more entertaining when the evil robots are still wobbling and eyeing you behind the menu buttons. How this is handled depends on your game. Since the evil robots in my game don’t move until the player moves, I just need to prevent the player from moving by checking if the game is currently paused.

2 Likes

I’d suggest avoiding using timeScale = 0f; method, as it is a bad practice.

At some point you’ll decide to implement something that moves / performs while game is paused, and that’s where the fun begins. As real time is not actually working properly on some devices.

As an alternatives:

  • Implement custom time manager.
  • Implement the “pausing” mechanism across the app, so you can access the pause and test if the app is paused.
    E.g. when checking player inputs.
1 Like

1 - Do you have a custom time manager or example to read ?

2 - You mean create an isPaused bool, lets say in playercharactermanager, and then in every Update() of every script begin with something like:

void Update()
{
if ( !isPaused) {
//do the stuff
}
} //End update

Thanks

I’d implement a static Pause class.
eg:

class Pause
{
     public static bool isPaused = false;
}

so you can just type

Pause.isPaused = true;
Pause.isPaused = false;

if (Pause.isPaused) {...}

from anywhere in every code in your game without needing to pass references.

Actually, i’d implement a game manager class which would do the same thing alongside some other unrelated things…

1 Like

Custom time manager is the manager that does exactly the same thing as Time, except it premultiplies deltaTime / fixedDeltaTime by the local time scale.

E.g.

public static CustomTime {
    public static float LocalTimeScale = 1f;
    public static float deltaTime {
         get {
              return Time.deltaTime * LocalTimeScale;
         }
    }

    public static bool IsPaused {
        get {
              return LocalTimeScale == 0f;
        }
    }

   public static float TimeScale {
        get {
             return Time.timeScale * LocalTimeScale;
        }
   }
}

That way you can replace the Time.deltaTime with CustomTime.deltaTime and alter the local time scale instead of an actual time scale. In this case UI won’t get paused, where as your logic will.

Alternatively this can be extended to check if the game is paused (LocalTimeScale == 0), or adding physics control (by using Physics.Simulate(Time.fixedDeltaTime * LocalTimeScale) and disabling the physics auto-sim.

This is rather versitile, especially if you want to do some slow-mo’s or rewinding / forwarding in time, as the local time scale can be extended to support multiple layers of timers. Imagination is the only limitation.

2 Likes

@edufissure , a better approach is to use a custom Update. E.g. what @Leonetienne500 wrote is the recommend approach. I’d just would not use Update because of the unecessary overhead but use something like a custom Tickable. Otherwise you will have to add the Pause.IsPaused boilerplate to any class. When you move that check upwards in the hierarchy, you have something like a TickManger who only calls Tick() when you are not paused and ITickable classes use the same pattern, but Update won’t be called every frame.

You can split the code you require to be run anyways from the code to be run when you are ticking by splitting it among Update/Tick/PausableTick.

An slight modification, could be to add a set and a get to make it more reliable and encapsulation ( be more in line wih oriented object paradigm) … ??

1 Like

So with your code, id only has to change Time.deltaTime by CustomTime.deltaTime…s

Yes, it is quite similar to what large assets does, such as Chronos.

1 Like

So would this ideas stop playing an animation ??

My idea is that when game over occurs, stop time ( no sense of player moving or enenmies or fireballs or whatever), but allow an end animation ( ex: dancing when winning, dying when loosing), and then show GameOver menu, with a message of victory or defeat, and restart, quit options…

Dont know the best way to implement this…

Thanks for your help…

No, it won’t stop them, unless you manually add a component that controls Animator via speed property.
E.g. Animator.speed = _initialSpeed * CustomTime.TimeScale.

1 Like

@edufissure , setting timeScale to 0 would probably solve your case just fine. No need to overcomplicate things.

If your things are still moving around after that, it means that you’re not multiplying time-dependent things by Time.deltaTime, which would already be a bug.

1 Like

I’m working on a simple game and this is the approach that I took to implement Pause Mechanism -

  1. I have created a PausableBehaviour class which inherits from MonoBehaviour.
  2. A GamePauseController uses FindObjectsOfType(); to get list of all the PauseableBehaviours. This controller also exposes Pause() and Play() methods.
  3. When Pause() is called, it disables all the components that implement PauseableMonobehaviour and enables them again when Play() is called.
public class PausableBehaviour : MonoBehaviour
{
}

    public class GamePauseController : MonoBehaviour
    {
        private PausableBehaviour[] pausableBehaviours;

        private void Awake()
        {
            pausableBehaviours = FindObjectsOfType<PausableBehaviour>();

            Debug.Log("Found " + pausableBehaviours.Length + "pauseable behaviours");
        }

        public void PauseGame()
        {
            foreach (PausableBehaviour behaviour in pausableBehaviours)
            {
                behaviour.StopAllCoroutines();
                behaviour.enabled = false;
            }
        }

        public void PlayGame()
        {
            foreach (PausableBehaviour behaviour in pausableBehaviours)
            {
                behaviour.enabled = true;
            }
        }
    }

This seems to work and gives flexibility in calling additional functionality when Pause and Play is called. For example, each behaviour can perform additional steps like stopping all co-routines or starting them.

This can be combined with a ScriptableObject which returns Time.deltaTime * scale. Set scale to speed up or slow down time for only specific behaviours.

    public class CustomTime : ScriptableObject
    {
        public float scale;
        public float deltaTime => Time.deltaTime * scale;
    }

I don’t know how the system will scale with different types of games. So let me know if you foresee any issues that it may run into.

1 Like

This is why I like to use only one MonoBehaviour script and then call updates on everything else manually; that way I am in complete control over every aspect that runs.

void Update
{
   if(pause)return;
   player.Update();
   enemies.Update();
}

This pattern is even better with events.

1 Like

Doesn’t this go back to the problem mentioned in the first few posts, where you may want some objects to still be able to move/interact/do something over time while the game is paused?

1 Like

At that point they can have the pause determine what does and what doesn’t run; structured however they want with as many different pause variables they want.

This blob goes in details about how the time scale effects different parts of unity. This will be helpful in deciding how to pause and run different systems like animations and audio if more control is needed.

1 Like
1 Like