Unity Tutorial - Scripting - Pausing and time control

 

Welcome to the first in what I hope will be a series of tutorials on a wide range of subjects. From here, I will discuss the how and why of my own professional dev processes, and try to share them with others so they can see how I do my own work.

Today, we will be discussing how to not only pause a Unity 3d game, but also how to slow down and speed up time during game play.  All scripting will be in Unity Script.  C# programmers should still be able to learn from this tutorial.

OVERVIEW:
We will be learning about how to control time in Unity 3D, and how we can use such control to essentially pause the game.  We will also learn how to still have timed features continue to work even while the game is paused, such as menus and other non in-game systems.

 

TUTORIAL:
First, you will want to look at the Unity variable for controlling the speed of time: "Time.timeScale".  When set to 1.0, Time moves at a normal pace, and all timers in unity move at the same speed.  When set to a number above 1.0, it speeds up time.  When set to less than 1.0, it slows down time.

You can change this variable, and all time variables will follow the new time scale.  All except "Time.realtimeSinceStartup".  This float will ALWAYS be the real time since the program started.

Another time function we use a lot of is "yield WaitForSeconds(foo)".  This function causes the program to pause at that point for 'foo' amount of seconds.  If the function was called from another function (such as Start() running a new function called "subfunction1893()") then the called function will pause, but the calling function will continue on as if a "return" was triggered.  This is called "creating a co-routine".  It creates another set of code that will run along side your main code.  If you want to learn more about this, I advise looking at " http://unity3d.com/support/documentation/ScriptReference/index.Coroutines_26_Yield.html " for more information.

Another way to do the same thing as "yield WaitForSeconds(foo)" is to use the following code:

var timertrigger = Time.time + foo;
while( timertrigger > Time.time )
{
    yield;
}

As you can see, we have a LOT more code to do the EXACT same thing.  So why do it this way?  What if you want it to DO something while waiting?  Not possible with "WaitForSeconds".  With the above code, you could change the code to allow you to do all kinda of things:

var timertrigger = Time.time + foo;
while( timertrigger > Time.time )
{
    xx = xx + 1;
    CheckForPlayerDeath();
    yield;
}

Now, can you do that other ways, and in other places?  Yes.  Options are nice to have, though.

Now, the above timers will always follow the "Time.timeScale" variable to determine speed.  If you set time scale to 2.0, then the above timers will run twice as fast.  It should be noted that it will not increase the framerate of the display, but it WILL effect the physics engine.

But what if you want a timer that ignores the time scale?

Try this code:

var realtimertrigger = Time.realtimeSinceStartup + foo;
while( realtimertrigger > Time.realtimeSinceStartup )
{
    yield;
}

And it's that simple.  The above timer will run in real time, ignoring what you have set "Time.timeScale" to.  This way you can tell time even when the game is being speed up or slowed down.

"But what does this have to do with pausing.  WAIT, I know!  Just set "Time.timeScale" to ZERO!  Right?"

No.  Never do that.  Bad!  Nonononono!

Seriously.  No.

Why?  Simple math.  You just set time to zero.  A lot of people DIVIDE by time variables. You just set everything to divide by zero.

Game over.  It crashes.

So, instead, we set "Time.timeScale" to a low fraction.  Like "0.000001", and use that for pause.  "But that's not paused, that's just really slow!"  Yup.  So slow you can't practically notice time passing.  Good enough for our use.

And that's it.  The above shows you how to control time in your game.  Just design around knowing what you want to have paused, and what you don't, and use the right code.

Hope this helps someone, and if you already knew this, then good for you!