Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Pause using Timescale=0

Discussion in 'Scripting' started by edufissure, Jan 21, 2019.

  1. edufissure

    edufissure

    Joined:
    Oct 25, 2018
    Posts:
    66
    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
     
  2. stefan_s_from_h

    stefan_s_from_h

    Joined:
    Nov 26, 2017
    Posts:
    72
    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.
     
    hank656 and lekkii like this.
  3. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    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.
     
    lekkii likes this.
  4. edufissure

    edufissure

    Joined:
    Oct 25, 2018
    Posts:
    66
    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
     
  5. Leonetienne500

    Leonetienne500

    Joined:
    Dec 5, 2016
    Posts:
    130
    I'd implement a static Pause class.
    eg:
    Code (CSharp):
    1. class Pause
    2. {
    3.      public static bool isPaused = false;
    4. }
    so you can just type
    Code (CSharp):
    1. Pause.isPaused = true;
    2. Pause.isPaused = false;
    3.  
    4. 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...
     
    xVergilx likes this.
  6. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    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.
    Code (CSharp):
    1. public static CustomTime {
    2.     public static float LocalTimeScale = 1f;
    3.     public static float deltaTime {
    4.          get {
    5.               return Time.deltaTime * LocalTimeScale;
    6.          }
    7.     }
    8.  
    9.     public static bool IsPaused {
    10.         get {
    11.               return LocalTimeScale == 0f;
    12.         }
    13.     }
    14.  
    15.    public static float TimeScale {
    16.         get {
    17.              return Time.timeScale * LocalTimeScale;
    18.         }
    19.    }
    20. }
    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.
     
    Last edited: Jan 23, 2019
    henners999 and Antypodish like this.
  7. MNNoxMortem

    MNNoxMortem

    Joined:
    Sep 11, 2016
    Posts:
    723
    @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.
     
  8. edufissure

    edufissure

    Joined:
    Oct 25, 2018
    Posts:
    66
    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) .... ??
     
    koyoco likes this.
  9. edufissure

    edufissure

    Joined:
    Oct 25, 2018
    Posts:
    66
    So with your code, id only has to change Time.deltaTime by CustomTime.deltaTime....s
     
  10. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Yes, it is quite similar to what large assets does, such as Chronos.
     
    MNNoxMortem likes this.
  11. edufissure

    edufissure

    Joined:
    Oct 25, 2018
    Posts:
    66
    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...
     
  12. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    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.
     
    MNNoxMortem likes this.
  13. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    @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.
     
    Kokowolo likes this.
  14. Pbasnal17

    Pbasnal17

    Joined:
    Oct 31, 2016
    Posts:
    2
    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<PausableBehaviour>(); 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.

    Code (CSharp):
    1. public class PausableBehaviour : MonoBehaviour
    2. {
    3. }
    4.  
    5.     public class GamePauseController : MonoBehaviour
    6.     {
    7.         private PausableBehaviour[] pausableBehaviours;
    8.  
    9.         private void Awake()
    10.         {
    11.             pausableBehaviours = FindObjectsOfType<PausableBehaviour>();
    12.  
    13.             Debug.Log("Found " + pausableBehaviours.Length + "pauseable behaviours");
    14.         }
    15.  
    16.         public void PauseGame()
    17.         {
    18.             foreach (PausableBehaviour behaviour in pausableBehaviours)
    19.             {
    20.                 behaviour.StopAllCoroutines();
    21.                 behaviour.enabled = false;
    22.             }
    23.         }
    24.  
    25.         public void PlayGame()
    26.         {
    27.             foreach (PausableBehaviour behaviour in pausableBehaviours)
    28.             {
    29.                 behaviour.enabled = true;
    30.             }
    31.         }
    32.     }


    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.

    Code (CSharp):
    1.     public class CustomTime : ScriptableObject
    2.     {
    3.         public float scale;
    4.         public float deltaTime => Time.deltaTime * scale;
    5.     }

    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.
     
    burakhandogan93 likes this.
  15. adehm

    adehm

    Joined:
    May 3, 2017
    Posts:
    369
    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.
    Code (CSharp):
    1. void Update
    2. {
    3.    if(pause)return;
    4.    player.Update();
    5.    enemies.Update();
    6. }
     
  16. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,894
    This pattern is even better with events.
     
    Kokowolo likes this.
  17. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    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?
     
    PraetorBlue likes this.
  18. adehm

    adehm

    Joined:
    May 3, 2017
    Posts:
    369
    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.
     
    Last edited: Jul 26, 2020
  19. Pbasnal17

    Pbasnal17

    Joined:
    Oct 31, 2016
    Posts:
    2
    rmgalante likes this.
  20. sundhar

    sundhar

    Joined:
    Aug 29, 2018
    Posts:
    3
     
    lekkii likes this.