The simplest approach to pausing your game in Unity is to set
Time.timeScale = 0. While the time scale is 0,
Update methods in your scripts will still called, but
Time.deltaTime will always return 0. This works well if you want to pause all on-screen action, but it is severely limiting if you need animated menus or overlays, since
Time.timeScale = 0 also pauses animations and particle systems.
We first encountered this limitation when we were trying to implement a world map in Lovers in a Dangerous Spacetime. When the player enters the ship's map station, we display a overlay of the current level. Since the map obstructs the ship and, as such, inhibits gameplay, we needed to pause the game while the display is visible. However, a completely static map screen would make it difficult to convey information (and also look pretty dull). In order to achieve our goal we needed a separate way to track how much time has elapsed since the last update loop.
It turns out that
Time.realtimeSinceStartup is the ideal mechanism for this. As its name implies,
Time.realtimeSinceStartup uses the system clock to track how much time has elapsed since the game was started, independent of any time scale manipulation you may be doing. By tracking the previous update's
Time.realtimeSinceStartup, we can calculate a good approximation of the delta time since the last frame:
This script on its own is not enough, however, especially since we want to use Unity's
Animation component to drive our dynamic map elements. To allow this, we created a subclass of
TimeScaleIndependentUpdate that manually "pumps" the animation:
normalizedTime property and our calculated delta time, we scrub through the animation in each
Update. Now all we need to do is attach this script to the GameObject we want to animate while
Time.timeScale = 0:
As you can see above, the game action is paused when the map appears, but the icons on the map are still animating. Particle systems can also animate while the game is paused.
ParticleSystem contains a handy
Simulate method which, similar to
Animation, allows us to manually pump the particle animation. All that's needed is a simple subclass of
We can combine these three scripts to create fairly complex sequences. In Lovers, once the player has collected enough friends to unlock a warp tunnel, we play a little cutscene while
Time.timeScale = 0:
This sequence relies heavily on the
TimeScaleIndependentWaitForSeconds method of
TimeScaleIndependentUpdate, which approximates Unity's built-in
WaitForSeconds method and is extremely useful for creating coroutines.