A common beginners mistake in game development is to implement the game loop by alternating between moving everything by a fixed amount of pixels and drawing everything. The problem with this approach is that the game will run slower or faster depending on the speed of the user's computer and on how much there is to update and draw at the moment. This is called "frame-dependent game mechanics".
One of the earliest examples of this is the good old arcade classic Space Invaders. You might remember that the game gets faster the more enemy ships the player destroys. It's not a feature, it's a bug! The game has frame-dependent game meachanics. The less enemies there are to draw and update, the more frames the arcade cabinet calculates per second. In this particular game it works because the game starts with a large number of enemies and progresses by reducing them, so the unintended speedup creates a nice difficulty curve.
But in most other games where the number of enemies on the screen just increases with higher difficulty, you would get the opposite effect. Situations which are supposed to be difficult become easy because they run in slow motion. Also, it only works when you target just one very specific hardware setup. When you target devices with different CPUs, your game will run slower or faster depending on the users device. That will make it impossible to deliver a consistent game experience.
But modern games rarely suffer from that problem. As you might have noticed from personal experience with high-end 3d games, the rendering framerate of games tends to go down when there are is a lot going on on the screen. But usually the game mechanics still run with the same speed, even when only 5 frames are actually rendered per second. That's because experienced game developers implement the game mechanics "time-dependent".
There are two approaches to this. The first thing you need to do in either approach at the beginning of your game mechanics update function is to check how much time elapsed since the last time it was called. Unity does this for you, but on other platforms you might have to do your own timekeeping.
One approach is then to take this time difference into account for every single game mechanics calculation you have. Unity makes this quite easy, because it exposes this information in the global variable Time.deltaTime
. When you use this technique with Unity, you should implement your game mechanics in the Update
functions of your MonoBehaviour and always take Time.deltaTime into account.
Another approach is to just perform multiple game mechanic updates until the simulated time has caught up with the real time. When you use Unity, you can let Unity do that for you, by putting your code into your FixedUpdate
function. Unity calls these functions a fixed number of times per second. But it is still good practice to use Time.deltaTime
in FixedUpdate functions, because you can change the timestep in the Time Manager. When you change the settings of the TimeManager and don't use Time.deltaTime in your scripts, it will affect everything handled by Unity itself but it won't have any effect on what your scripts are doing. This is going to end badly. So either use Time.deltaTime or remember to never touch the TimeManager.