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.
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.
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.
@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) … ??
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…
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.
@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.
I’m working on a simple game and this is the approach that I took to implement Pause Mechanism -
I have created a PausableBehaviour class which inherits from MonoBehaviour.
A GamePauseController uses FindObjectsOfType(); to get list of all the PauseableBehaviours. This controller also exposes Pause() and Play() methods.
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.
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.
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?
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.