All About Time in Unity Game Engine
In this blog post I talk about Unity’s Time
class along with a couple of related settings and components. Time is a fundamental concept that any game developer needs to master. It doesn’t matter if you are making a 2D or 3D game. It doesn’t matter if you are making an RPG, FPS, farm simulator or a fighting game. You’ll have to deal with time constantly as you develop a game. As your become more familiar, it becomes second nature.
Unity has many features for managing time. Time
class alone has Time.FixedDeltaTime
, Time.CaptureDeltaTime
and Time.timeScale
. It is safe to say that every Unity developer has gotten confused by the plethora of Time settings in Unity.
This is a in-depth blog going into details of Time management in Unity. I’ve tried to cover everything that could possibly be related to time. Some things may initially seem unrelated, like Frames-per-second (FPS) or Rigidbody
component’s animation properties. But as you will see, they all tie in together nicely.
You should be familiar with Unity at least at a beginner level to benefit most from this blog post. Having some programming background helps with understanding of the inner workings of Unity.
I have also made a sample Unity project that you can download and play around with. The project is called “Unity All About Time” and is available here:
For the ultra-lazy I’ve hosted the webgl build of project on github as well. You can try out the demo project in your browser with the link below. Anywhere you see a “hands on” icon throughout this post, you can go there and try it out for yourself! I highly encourage you to try the project as you read this blog to get a better feel for the features we discuss.
https://github.com/hk1ll3r/Unity-All-About-Time
Here are a few questions that you will be able to answer after reading this blog post:
- What is FixedTime? Is FixedTime different than game time?
- my game’s time somehow got tied to FPS!!! objects move faster not smoother with more FPS!!!
- will slow motion and fast forward change the outcome of my game’s physics simulation?
- How should I adjust targetFPS and physics delta time in my game? What factors affect my decision?
- What is Time.CaptureDeltaTime?
If you don’t know some of the answers, that’s fine. This is your chance to learn!
You know all the answers? You are a Unity expert! This blog post will not add much to your knowledge. However if you want to refresh your memory, read on!
(game) time, fixed time and real time
First, let’s make the distinguish between real time, game time and fixed time.
Real Time: Time in real world outside of the game. What your watch shows. It can’t be stopped, slowed, rushed or changed (not considering Einestein’s relativity).
Game Time: Time in the game. In Unity docs and classes usually referred to simply as time. Usually it advances at the same rate as real time, but using Time.timeScale
and other settings, one could make it advance slower or faster compared to real time. Slow motion, fast forward and pause features in many games use Time.timeScale
.
Fixed Time: is a term used by Unity to refer to physics engine time. Unity has physics engines integrated behind the curtains. When you add a Rigidbody
component to a GameObject
, that object gets added to the physics scene and receives updates from gravity and other physics forces and collisions.
Ideally fixed time and game time would be fully in sync. However in reality they usually diverge by very small amounts. As long as the difference is small enough, the users won’t notice it and all will be fine.
Unity All About Time App
Let’s familiarize ourselves with the “Unity All About Time” app accessible here. It is an easy to use Unity application I’ve made that let’s you play with different controls from within the app. The sample scene has a very simple setup. A plane and a bouncing ball. On the left are the sliders to control different settings. On the right some measured statistics are displayed.
The statistics on the right include:
FPS: Frames displayed per second of real time.
FFPS: number of physics step calls made per second of real time.
realT, unscaledT, fixedT, gameT: Different times we discussed before. realT and unscaledT are the same. FixedT is fixed time also known as physics time.
Display Refresh Rate: The number of frames displayed by the current display, probably your laptop or tablet screen.
In the course of this blog post I will explain the left side controls and how they affect game time. Just to see how the controls work, let’s change the Balls control to change the number of balls in our simulation.
For accurate control and for the keyboard savvy, each control has a shortcut. You can use the shortcut to loop through some predefined values for that control. Press ‘b’ while the game window has focus to see the shortcut for balls control in action.
The balls stop bouncing and get stuck in some extreme cases that we explore in this blog post.
You can reset the simulation with the ‘r’ key.
Game Loop
Most games have a game loop that continuously runs and updates the game world as time advances. It is key to understanding how a video game simulates time. Let’s take a look at a very basic game loop:
1 Loop {
2 GameTime += RealTime - LastRealTime
3 LastRealTIme = RealTime
4 While FixedTime + FixedDeltaTime <= GameTime
5 SimulatePhysicsStep(FixedDeltaTime)
6 FixedTime += FixedDeltaTime
7 // physics is caught up to game time
8 RenderFrame()
9 }
Here is some explanation for the “psuedo-code” above.
- Line 2: game time advances to match real rime.
- Line 3: saves current real time for next iteration of the loop, a technical detail.
- Lines 4–6: physics engine steps enough times so that fixed time (physics time) catches up with game time.
- Line 7: // marks a code comment, has no effect.
- Line 8: a frame is rendered to be shown to the user.
The loop ensures two key principles:
- Fixed time is always as close as possible given the current parameters to game time when a frame is rendered. As we will see later, fixed time can be slightly behind game time at render time.
- We use the maximum computation power we can. prioritizing physics updates to frames, but if we can keep up the physics time with game time, then we render as many frames as possible!
Now that we have seen the app, let’s go back to the game loop. Consider the following cases to help the idea of the game loop sink in.
Fixed Delta Time
make sure the left side controls are set to the their initial values shown below. If you have changed them, set them back to these values or simply refresh the web page or game scene.
Specifically we want:
- TargetFPS to be -1
- VsyncCount to be 0
- CaptureDeltaTime to be 0
With these settings Unity’s game loop will behave like the simple version we sketched above.
The FPS can be any value but typically between 30 to 60+, as many as your current PC can produce. However FFPS, the number of physics steps per second of real time should be 50. Fixed Delta Time: 0.02 means we will have one physics step call per 0.02 of game time. Game time and real time advance at the same pace with these settings. You can verify this on the right hand side. Notice how gameT, FixedT and realT advance at the same pace.
Play around with Fixed Delta Time
Let’s increase the Fixed Delta Time control to 0.1. In this case we will have 10 physics steps per second of game time which advances at the same pace as real time. You should notice some “laginess” in the movement of the balls. Note that the FPS stat, that is number of rendered frames, will depend little on the Fixed Delta Time, but FFPS stat, the number of physics steps per second will decrease to 10.
To exaggerate this effect even more, set Fixed Delta Time to 0.25. In this case the simulation will look even more laggy. Can you guess the value of FFPS stat in this case? … The answer is 4 because
Game Delta Time = 1
FFPS = Game Delta Time / Fixed Delta Time = 1 / 0.25 = 4
The following images show the game with different Fixed Delta Time values.
So high values of Fixed Delta Time will cause laginess. To understand why, look at the following grpahs. These graph shows the occurrences of Physics steps (line 5 of the previous game loop code) in orange and occurences of frame renders (line 8 of the previous game loop code) in green.
Note that the frame renders happen at a high FPS in both cases. In the above graphs around 15 FPS. Yet all the renders between the physics steps (adjacent orange lines) render exactly the same frame! Essentially wasting the processing power of our PC. The higher the Fixed Delta Time, the farther apart physics update calls will be, and hence more frame renders will be identical.
Fixed Delta Time and stability of physics simulation
One important thing to note here is that Fixed Delta Time affects the outcome of physics simulation. Because the physics engine will simulate a larger time span in a single step. You can see this effect by increasing Fixed Delta Time and resetting the simulation (shortcut ‘r’). Next decreasing Fixed Delta Time to its default value 0.02 and reset again.
Smaller values of Fixed Delta Time make up for smoother, more accurate physics simulation.
You might be wondering why we don’t always set Fixed Delta Time to the smallest possible value? That’s because in a real game with thousands of physics objects, the physics step becomes computationally expensive. It can then deteriorate performance and drop FPS. In our sample however both rendering a frame and taking a physics step take almost no time. Therefore the FPS will not get affected even with a Fixed Delta Time value of 0.01.
Time Scale
The next control we are going to look at is the Time Scale. It is a very important setting that can help us implement slow motion, fast forward and pause in our games. Let’s update the game loop to account for time scale:
1 Loop {
2 GameTime += (RealTime - LastRealTime) * TimeScale
3 LastRealTIme = RealTime
4 While FixedTime + FixedDeltaTime <= GameTime
5 SimulatePhysicsStep(FixedDeltaTime)
6 FixedTime += FixedDeltaTime
7 // physics is caught up to game time
8 RenderFrame()
9 }
The only change is in the second line. The delta time is multiplied by timescale! It’s a very simple change indeed, but it can cause complex interactions. Let’s explore this newly found control!
Time Scale: Pause
Set the Time Scale control to 0. Then you should see the balls stop. This is a very common way to implement pause in video games.
Notice that while FFPS stat hits 0 and no physics steps take place. However FPS stat stays where it was. The game loop is still running! The game time doesn’t advance (Line 2) and as a result no physics steps take place. You should see this on the right side of the game window. FPS will be the same as before and real time keeps increasing. While game time and fixed time will be stopped.
Time Scale: Fast Forward
Set the Time Scale control to 5. You should see the balls bouncing around faster in the simulations. Just as one would expect. Notice that increasing Time Scale doesn’t increase FPS because it takes the same amount of time in real time for your GPU to render a frame. However we will end up with proportionally more calls to physics step and a higher FFPS stat.
If this confuses you take a look at the latest game loop code by scrolling up. In Line 2, a higher value of Time Scale causes a more rapid increase in the value of game time. However each physics step still takes the Fixed Time forward the same amount (Fixed Delta Time). So the loop on lines 4 to 6 will have to run more times to account for the bigger change in game time.
Intuitively, each physics step advances physics time by a fixed amount (Fixed Delta Time) and if game time is moving faster, we need more physics step calls to compensate.
Time Scale: Slow Motion
This time around set the Time Scale control to 0.1. That causes the FFPS stat to become 5. Let’s do the math:
Real Delta Time = 1
Fixed Delta Time = 0.02
Game Delta Time = Real Delta Time * 0.1 = 0.1
FFPS = Game Delta Time / Fixed Delta Time = 0.1 / 0.02 = 5
Similar to the case with increased Fixed Delta Time before, e are calling the physics update only a few times per real time second. And that causes the animation to become laggy. So not a good slow motion. To avoid this laggy behavior we could multiply Fixed Delta Time by Time Scale. Let’s go ahead and do that. Change Fixed Delta Time to 0.01. That will make the simulation run smoother.
But decreasing Fixed Delta Time for slow motion isn’t always desirable. Remember that changing Fixed Delta Time alters the outcome of physics! For multiplayer games for example, or to keep the game simulation reliable, you may want to not do that. Let’s see how else we can make the simulation run smoother.
Rigidbody’s Interpolation Property
In the cases where we don’t want to decrease Fixed Delta Time, Rigidbody component’s interpolation property is a good feature to make the animations smooth! Compare this with the previous video and compare for yourself.
In this case, instead of moving the rigid body to its final pose, the physics engine leaves the actual update of pose and velocities to the render phase. So even if no physics steps are made for some consequetive frames, the objects will still move as if they are under physical effects. Note that the objects won’t collide or actually get affected by forces, they just move smoothly towards a predetermined location from the previous physics update.
FPS (Frames Per Second)
So far we had Target FPS set to -1, so we would get as many frames as possible (or up to 60 in the browser). But more rendered frames isn’t always better! On beefy computers a common bottle neck to the number of frames the system can display is the screen’s refresh rate. You can’t show more frames than that even if your graphics cards can produce them. So a natural upper limit for FPS is screen’s refresh rate. Nowadays there are talks of 120Hz and 240Hz instead of the common 60Hz refresh rates. Unless you have one of those fancy monitors, 60 FPS is probably the highest you are going to get.
Note that FPS is always measure in real time!
Target FPS
Let’s play around with the Target FPS control. As the name suggests, this control limits the maximum number of frames the game loop will produce.
Up to this point the Target FPS control was set to -1. -1 is a special value and has different meaning depending on the platform your Unity app is running on. In the Editor it means as many frames as possible. In web it means 60 for the most part.
Target FPS: Moderate Value
Change the Target FPS control to 20. You should see the FPS stat on the right side reflect that. It may take a few seconds for the stat to converge. Unless your PC is really slow and cannot render 20 frames per second.
Target FPS: High Value
Set the Target FPS control to a high value like 120. If you have a beefy PC, you will get an actual FPS of 120. If not, you will get as many frames as your PC can generate. Maybe 40, maybe 60, maybe some other value. The value will be the same as settings Target FPS to -1.
Target FPS: Small Value
Finally, set Target FPS to 10. It should not be a surprise that the ball animations look laggy.
The following graph shows the reason for laggy animations in this case. As you can see this time around there are quite a few physics updates in between frame renders, so the balls have moved a significant amount between frames.
This time the Rigidbody’s interpolation won’t fix the problem. We are simply generating a small number of frames to display. The only way to fix this type of lag is to lower the graphics and physics load in the scene so that the system can render frames faster.
Let’s update the game loop from before with the FPS limiting functionality:
1 Loop {
2 GameTime += (RealTime - LastRealTime) * TimeScale
3 LastRealTIme = RealTime
4 While FixedTime + FixedDeltaTime <= GameTime
5 SimulatePhysicsStep(FixedDeltaTime)
6 FixedTime += FixedDeltaTime
7 // physics is caught up to game time
8 RenderFrame() 9 WaitForScreenOrTargetFPS()
10 }
The logic for limiting FPS is not too complex but not trivial either. Usually it involves tracking the historical FPS and waiting assuming the current render will take the same time as the current running average.
VSync
“Tearing” is a graphics artifact that happens when GPU renders a frame while the screen hasn’t finished showing the previous frame. The screen switches to the newly generated frame in the middle of the refresh. As a result half of the screen will be from one frame, and the other half from another frame.
Luckily the mighty engineers who made GPUs and monitors thought about it and came up with the Vsync feature. It basically syncs displaying the rendered frames to the next screen refresh.
You can enable VSync by setting the VSync Count control to a non-zero value. When enabled, it override the Target FPS control and frames are rendered for every Nth screen refresh. VSync Counc can take integer values from 1 to 4. Assuming a screen refresh rate of 60, VSync Count values of 1, 2, 3 and 4. result in 60, 30, 20, 15 FPS respectively.
The vsync feature doesn’t work on my linux distro. I’m pretty sure it will work on Windows and Mac. In any case I hope it works for you in your setup. Let me know how it goes for you!
VSync Count
Set VSync Count to 0 if it is not already and see how Target FPS control determines the FPS stat.
Now set VSync Count control to other values and see the FPS change as multiples of Screen’s Refresh Rate stat.
Hope you were able to catch up to this point. If your brain is hurting, it is understandable. But hang on! There is one last feature we need to discuss!
Capture Delta Time
Up to now game time always advanced proportional to real time. There are cases like rendering animations or capturing screen for demos and videos in which we want a guaranteed FPS. To achieve that, Unity supports a mode in which the game time advances per rendered frame instead of real time! It no longer matters whether we have a beefy computer or slow pentium II form the 90s. They produce frames exactly at the same game times. So a faster machine would finish faster where as a slower machine would take longer to produce the same results.
In short, with a Capture Delta Time of 0, game time advances with real time. Only timescale can make it run faster or slower than real time. Still game time always advances proportional to real time. A beefy computer could generate more frames than a sluggish computer, but game time would advance at the same pace on both computers. Here is how the frame render and physics step calls graph would look like for a fast and a slow PC when Capture Delta Time is disabled (0)
Here are two key points to note about the above two grpahs:
- Note that game time and real time are in sync in both cases.
- In both cases there are the same number of physics steps in each second (orange lines). The faster machine will simply have a higher FPS.
With captureDeltaTime > 0, slower machine will advance gametime slower, but at the same framerate as the beefy computer.
Here are two key points to note about the above two graphs:
- Note that game time and real time are no longer in sync. Game time advances with each frame.
- In both cases, there are the same number of physics steps between frames.
Capture Delta Time therefore causes game time to advance at variable speed depending on the content that is being rendered in each frame. It is not suitable for video games, but it is very useful for rendering offline content like animations.
Feel like losing your mind yet? If so that’s fine. Our human brains needs time to soak all the info. Maybe you can read this section on Capture Delta Time later as well.
Let’s update the game loop one last time to account for Capture Delta Time:
1 Loop {
2
3 if (CaptureDeltaTime is 0)
4 GameTime += (RealTime — LastRealTime) * TimeScale
5 else
6 GameTime += CaptureDeltaTime * Time.timeScale
7 LastRealTIme = RealTime
8 While FixedTime + FixedDeltaTime <= GameTime
9 SimulatePhysicsStep(FixedDeltaTime)
10 FixedTime += FixedDeltaTime
11 // physics is caught up to game time
12 RenderFrame()13 WaitForScreenOrTargetFPS()
14 }
In line 6, if Capture Delta Time is non-zero, we advance the time by a fixed amount, similar to what we do for physics steps.
Play Around with CaptureDeltaTime
- Let’s go ahead and set CaptureDeltaTime to 0.02. Do it by pressing ‘C’ enough times. If you miss it keep pressing ‘C’ until the slider resets to zero and then to 0.02. Make sure the Time Scale is set 1.
In this case we expect the FPS to be equal to FFPS because Capture Delta Time is the same as Fixed Delta Time. Line 6 advances game time by 0.02 and the physics loop in line 8 runs once and syncs physics time with game time. - Now change Capture Delta Time to double the Fixed Delta Time. In this case FPS should be equal to half of FFPS. I leave it to you to figure out why.
Also note that game time is tied to FPS instead of real time when using the Capture Delta Time feature. To get a feel for it, make sure VSync is set to 0 and increase and decrease the Target FPS control. Notice how it indirectly affects the pace at which game time advances. If Capture Delta Time is 0, a higher FPS causes smoother animations but the same pace for game time.
Additional Controls: FrameProcessingTime & PhysicsProcessingTime
It is worth mentioning the last two controls in the app. They slow down rendering and physics steps by a certain amount of real time. You can use those for simulating graphics heavy or physics heavy games. I use Thread.Sleep for the implementation which doesn’t work in the webgl build unfortunately. You’d need to try it in the Editor or on another Unity Player to use them.
Conclusion
If you made it this far congratulations! You made it! Now you are a guru in Unity’s time… or at least a bit more familiar and fluent with Unity and its time management features. Pat yourself on the back!
Have any questions about the features discussed in this blog post? Were parts of this guide not easily understandable? Let me know in the comments.
If you found this guide useful, consider supporting me on Patreon. It helps me focus on writing more of these blog posts and spending more time on game development.
Cheers!