I hope you’re ready for another exiting edition of Feature Fridays! I’m not going to waste any time before talking about the feature we’ll be looking at this week: Time!
As video games are ran and simulated in real time, the concept of time sits at the core of the games we create. Fully understanding the ways time works in Unity will allow us to deliver better and more engaging experiences to our players.
So today we’ll discuss:
- How Time Works in Unity
- Fixed Time
- Modifying Time (Fast/Slow Motion)
And don’t forget, at the end of each Feature Friday article, I feature a game, tutorial, or asset store tool made using the Unity game engine. This week we have an asset store tool that relates directly to the topic of this article.
So now it’s time to learn about time.
1. How Time Works in Unity
Throughout this article, we will heavily be referencing the Time class. The Time class is a class that is built in to Unity and contains several properties related to, you guessed it: time!
This is one that is extremely important to familiarize yourself with as you will likely be using it in at least a few places in each of your game projects.
In Unity, time values are stored in float type variables and represent a precise number of seconds.
Take for example
Time.time – this property gives us the number of seconds our application has been running for. At the precise moment that our game begins,
Time.time will begin counting up.
If our game first loads into a main menu, then the player selects a level to play in, that same time value continues to increase. Of course we cannot set the
Time.time value manually – or else we would totally break the game engine – but we still can check to see what the value is at a given moment in time.
var currentTime = Time.time;
In this case, the value for
currentTime will be equal to the number of seconds elapsed since the game has loaded, at the beginning of the current frame. I specify that this value is taken at the beginning of the current frame, because as we will see later, a frame spans over the course of a few milliseconds and the time values would be different at the beginning and end of each frame.
Now what if we only cared about how long our player has been in a particular level? Well there is another Read-Only property we can reference,
Time.timeSinceLevelLoad. As the name suggests this is the amount of time since the current level has loaded. Again the time is taken at the beginning of the frame and is a value in seconds.
Another important concept that I’ve alluded to is the idea of framerate. Framerate is defined as the number of frames drawn to the screen in one second. A frame is just a still image on the screen and these frames being played rapidly gives the illusion of motion.
If we draw 60 frames to the screen in one second, then we can say that our game is running at a framerate of 60 FPS (Frames Per Second). Often computer monitors will advertise their maximum framerate in hertz (Hz), which is fundamentally the same thing.
If we take the reciprocal of our framerate, we get the frame time – or the time it takes to draw one frame to the screen.
60 FPS is 60 frames over 1 second, so the reciprocal is 1 over 60.
1 / 60 = 0.0166667
Frame time is most commonly expressed in milliseconds so we can multiply our result by 1000 (or just move the decimal three places to the right) to get a value of 16.6667ms.
Many developers refer to the frame time as like a budget. If they are targeting a framerate of 60 FPS, then their frame budget is 16.6667ms. Knowing that some amount of time will need to be dedicated to taking input, simulating physics, running algorithms, and rendering the frame – these things begin to chip away at the frame budget and you are only left with a certain amount of time to do anything else you want to do in a given frame.
One thing to know about Unity games specifically, is that they do not usually run at a fixed framerate. This means that sometimes it takes longer to render a frame than other times. As such, our frame time value is constantly changing. If the game is running at a steady framerate, the frame time values frame to frame will be close but usually not exactly the same.
In Unity, the property
Time.deltaTime gives us the frame time of the previous frame.
Time.deltaTime is literally the delta, or difference, between the
Time.time values of the current and previous frames.
If the time on a frame is 41.02 seconds and the time on the following frame is 41.04 seconds, then the
Time.deltaTime value on the latter frame would be 0.02 seconds or 20ms.
By continually adding
Time.deltaTime to a variable in our game, we can effectively have a timer that updates every frame.
Time.deltaTime is a very important concept to know about, because we can use it to normalize motion irrespective of framerate.
To demonstrate this, let’s look at a simple example. Let’s say our game has vehicle in our game that moves two units forward for every frame.
If our game was running at 100 FPS on a high end PC, then the vehicle would move 200 units in one second.
If our game was running at 25 FPS on a mobile phone, then the vehicle would move only 50 units in the same amount of time.
As you can see, this could be a big problem because you can never rely on the framerate being a specific value – even if everyone is running the game on the same hardware.
Using frame time, if we multiply the distance traveled by
Time.deltaTime, this effectively normalizes the distance traveled each frame, so the vehicle travels the same distance over the same period of time on any device.
Just to prove to you that the math checks out: 100 FPS has a
deltaTime of 0.01 seconds – meaning the vehicle would travel 0.02 units every frame, and that distance over 100 frames is 2 units every second. 25 FPS has a
deltaTime of 0.04 seconds, so the vehicle goes 0.08 units every frame, multiply that by 25 frames, and again the vehicle travels 2 units.
Although the vehicle travels a larger distance over each frame on the mobile device, it doesn’t draw as many frames, so the vehicle travels the same distance over the same amount of time on every device.
So this is why time is extremely important to understand, because it can have direct impacts on how your game is played. Now let’s talk about another type of time we will come across when making games in Unity.
2. Fixed Time
Aside from regular time in Unity as discussed above, there is another very important type of time to know about and that is fixed time. As we just learned, regular time is variable and can frame time can be faster or slower depending on our game and the hardware it is running on. On the other hand, fixed time, as the name suggests, is fixed and will always run on constant intervals.
One common system used in Unity that runs on a fixed time interval is the physics system. This must run on a fixed time interval as even slight variations in this interval can have large impacts on how the physics in a game are calculated. The last thing you want happening in your game is having an inconsistent and unpredictable physics system only because of miniscule changes in frame rate.
By default in unity the fixed timestep is set to 0.02 or 50 iterations per second. You can set this value to whatever you want in the Unity editor by going to Edit > Project Settings and updating the Fixed Timestep value under the Time category.
If you ever need to reference the elapsed fixed time, just get the value from the property
Time.fixedTime and the fixed frame time is stored in the property
As you likely know, the
Update() method in MonoBehaviour scripts is called once every frame. There also is a
FixedUpdate() method that is called once every fixed timestep. This is often where you want to contain code for motion as it always runs at the same rate regardless of framerate.
Now that we understand how regular and fixed time work in Unity, let’s break all of that.
3. Modifying Time (Fast/Slow Motion)
The Unity game engine gives us the ability to modify the rate at which time passes in our game. This is done by setting the
Time.timeScale property. By default
Time.timeScale is set to 1.
The time scale determines how fast or slow time passes in your game. A time scale value of 2 would make your game run at double the speed it normally would. A time scale of 0.5 would make your game look as if it was running a half speed. A time scale value of 0 would effectively pause your game.
And no, a negative time scale value unfortunately does not play your game in reverse 🙃
Now up to this point, all the time values we have been looking at are part of scaled time, meaning that changing our scaled time affects things like the
For example if we set the time scale to 0 to pause our game when
Time.time was at 48 seconds,
Time.time would NOT continue to increase. Even if the game was paused for an hour, when we resume the game (set time scale back to the default value of 1)
Time.time would still be just after 48 seconds.
Luckily, in case we still do need to keep track of things independent of the time scale, we have access to the
Time.unscaledTime property. This property represents the true time the application has been running – it doesn’t matter if the game was paused or sped up at any point for any duration.
We did briefly touch on this in our overview of coroutines a few Fridays back where if we want to wait for a certain amount of time regardless of the speed the game is running at, we could use
Now this time scale is a global property so you cannot set things to run at different time scales, though you could make it so some things are moving at scaled time and other things are running at unscaled time for some cool effects.
Or you could always look into a third party solution where you can really take advantage of interesting time related things. One such example is the featured Unity Asset Store tool of the week.
Featured Unity Asset Store Tool of the Week
I’m sure you are now all fired up to play around with the time settings in your game. And while you do that, you might also want to download Chronos from the Unity Asset Store (free asset).
With Chronos, you can do the standard speeding up and slowing down of time, but you can also rewind time.
Better yet, you can override the time scale settings on a per object or even area of effect basis.
If you are making a game where you want to do fun and unique things with time, then this asset is a must have.
So I do hope that you enjoyed your time learning about time, and until next time, keep on creating!
Turbo Makes Games