Sponsored By

Pausing and Time Management in Unity

In this week's PuckMania Developer's Blog, we talk about a simple and common way to implement pausing in Unity.

Marc Breaux, Blogger

October 7, 2014

6 Min Read
Game Developer logo in a gray background | Game Developer

I want to talk about a less exciting aspect of video game construction:  Pausing the game.

This isn't really a flashy or impressive area of game design, and I would guess that young future game devs aren't inspired by the pause menus of their favorite games the way they might be by their controls, graphics, etc.  It seems like such a simple thing that you'd be forgiven for not even thinking about it until you have to make it work in your game.

Today I'm going to write a bit about a common way to implement pausing in Unity, as it pertains to time and movement.

But before that, a little reminder about...

...Frame Independent Movement

This is pretty basic, but it's worth reviewing because it informs everything else we're talking about here:  All of your movement should be independent of the frame rate.  This means scaling non-physics movement by Time.deltaTime in Update(), and physics-based movement (over multiple frames) by Time.fixedDeltaTime in FixedUpdate().  In addition to ensuring that your game appears to run at the same speed regardless of the frame rate, this is going to enable us to utilize some tricks with the game clock, as we'll see below.

Pausing The Game

In theory, this should be simple enough.  Just create a flag called "Paused" and use it to bypass any movement updates in Update() and FixedUpdate() when set to true, right?  But how do you pause a physics rigidbody then start it up again, as if it had never stopped?  And how do you ensure that processes that are trying to move objects via their transform will pick up where they left off?  This turns out to be potentially complicated.

But Unity gives us a pretty handy mechanism that works very well if all of your movement is frame rate independent (as it should be, always!)  Time.timeScale can be set to change the rate at which time passes.  You can speed up or slow down your game, or even stop it entirely setting Time.timeScale = 0.

When Time.timeScale is set to zero:

  • Time does not pass, so Time.deltaTime will equal 0 in every frame.  So all of your frame independent code which uses it will stop moving.

  • Update() continues to be called.   This will allow you to continue processing in the background - important for eventually unpausing the game and any other interactions that you want to do while paused.

  • FixedUpdate() stops being called.  The physics engine is also paused.

Doing Stuff While Paused

So that was relatively simple.  Set Time.timeScale to zero to pause the game, and set it back to 1 to unpause it.

But what if we need to do some frame independent movement while the game is paused?  For example, an animated or moving pause menu UI over the game, like so:

It's paused. Whoopee! It's animated.  Just go with it.

Like we said before, Time.deltaTime becomes 0 when timeScale is set to 0, so that's not going to work for us.

But there is a way.  Unity gives another value called Time.realtimeSinceStartup.  This is the total amount of time in seconds that have elapsed since the game started, and this is unaffected by timeScale.  This, combined with the fact that Update() continues to be called, presents us with a way to compute our own deltaTime that is immune to the time freezing effects of timeScale.

In PuckMania, I've created a very simple class to keep track of this.  I call it TimeController because controlling time has always been a fantasy of mine, and this is as close as I'll ever come *sigh*:


using UnityEngine;
using System.Collections;

public class TimeController : MonoBehaviour {

    public static float deltaTime;
    private static float _lastframetime;
	void Start () {
        _lastframetime = Time.realtimeSinceStartup;
	}
	
	// Update is called once per frame
	void Update () {
        deltaTime = Time.realtimeSinceStartup - _lastframetime;
        _lastframetime = Time.realtimeSinceStartup;
	}

}

Were you hoping for complicated and fancy?  Sorry to disappoint, we're keeping our Unity hacks simple but still powerful today.

How this works is very simple:  You attach a TimeController to a single object, preferably something that will be present in every level that needs it.  PuckMania uses a persistent "GameController" object  in every scene, so I've attached a TimeController to that.

Then from there, for frame independent movement that needs to be processed even when paused, you use TimeController.deltaTime instead of Time.deltaTime.

Conclusion

That's really all there is to a basic pausing mechanism that should work well in most projects.  If you're sticking with the best practice of using frame independent movement in your code, you'll find that you shouldn't need to modify your code too much to get the game to stop and start without a hitch.

Thanks for reading, and keep checking us out at www.puckmania.com!
-Marc

Originally posted at: http://www.puckmania.com/blog/pausing-and-time-management-in-unity/

Read more about:

Featured Blogs
Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like