The question about
fixedUpdate: in Cocos2D (
FixedUpdate in Unity) appears quite regularly on different forums. It was answered many times. However, even after getting the answer some people still have some questions.
The typical answer to this question is that
update: is called once per frame and
fixedUpdate: is called at constant rate.
fixedUpdate: in Cocos2D-Swift (ex. Cocos2D-iPhone), but same can be said about the
FixedUpdate methods in Unity.
But what does that mean? And more importantly, when should you write your code in the
update: method and when to use
fixedUpdate: in Cocos2D?
The game as a set of frames
Before understanding where should you write the code, lets question ourselves why do we even need to write the code at all?
Sounds like a crazy question. Of course we write the code to move our game objects, update labels, calculate hit points, path finding and so on. But what is the result of the execution of the most of our code?
The result is what you show on the screen. The current frame.
It doesn’t matter what type of game you create, how many layers of abstraction you have in your code or what patterns you use. In the end your game will be simply displayed frame by frame on the player’s device screen.
Of course we get user input, simulate physics and do many other things that player won’t see, but in the end the only thing that matters is what the player sees on the screen. This is the game from the player’s point of view.
Now, let’s get back to our update methods.
The purpose of the update: method
The purpose of the
update: method is to give you an opportunity to update your game (all of your game objects, labels and so on), just before they are rendered on the screen.
In other words if you want some game object to be displayed at some position on the screen, you update its position inside the
update: method. Then the whole scene is rendered and you can see your sprite or a label right where you put it.
Imagine you are working on a game where the player throws the ball. The ball flight might look like this:
Everything looks good, the ball was rendered 8 times in 8 different positions while it travels from start to finish. This means that the
update: method was called 8 times. It was called once for each ball position shown on the preceeding image.
Now, imagine that the game’s frame rate drops for some reason. You render the ball at its starting position (1), and then the game freezes for the whole
1s interval. So the next time your code is executed is when the ball should already be at position (8).
Yes, the situation is bad, the player won’t see that smooth movement. However, we can do nothing about it. The player expects the ball to be at position (8) after waiting for
1s, so we should place the ball there.
There is one interesting question. Should we render the ball at positions 2-7?
Or, if I rephrase the question, do we need to execute the code of the
update: method to change position of the ball 8 times (so that it was displayed at this position) or only 2 times?
The player won’t see those intermediate frames anyway, because the ball should travel the whole distance. So there is no reason to execute the code of the
update: method for positions 2 – 7.
This means, that the first time
update: is executed the ball is at position (1) and the second time
update: is executed we put the ball straight to position (8).
The purpose of the fixedUpdate: method
Now, imagine that there is a moving platform between the ball’s positions (1) and (8).
The platform is moving up and down. Sometimes the ball flies without touching it and sometimes it collides with this platform.
This means that the ball can end up at position (8a) or (8b).
We still don’t need to render all the intermediate positions, because the player won’t see them. But how do we know where we should display the ball, at position (8a) or at position (8b)?
This is where
fixedUpdate: comes to the rescue. The
fixedUpdate: method will be executed for all those intermediate positions, which we skipped because of low frame rate.
This way, at position (4) we can check if the ball collides with the platform and modify its trajectory.
How update: and fixedUpdate: are called in reality
update: method is called once per frame to give you the chance to update your game objects right before they will be drawn. And the
fixedUpdate: method is called at constant rate to give you the chance to react on situations that happen between the frames, even if the frame rate drops.
Here is the situation when the frame rate is high and stable:
update: interval and
fixedUpdate: interval are by default set to
1/60th of the second, so in ideal world we would get the situation shown on the preceding image, where
fixedUpdate: are executed always at the same time.
However, in the real world, more often you can experience the following situation:
And sometimes even following:
How this works
The code that calls both the
update: and the
fixedUpdate: methods works this way.
Cocos2D gets the time interval(delta) since the last time your game’s code was executed by iOS and checks how many
fixedUpdate: method calls should have occurred during this time interval. Then Cocos2D calls the
fixedUpdate: method required number of times.
In other words it just breaks time interval into identical chunks and calls the
fixedUpdate: method once for each full chunk. This is why the
delta parameter passed to
fixedUpdate: is always constant and set by the
CCSetupFixedUpdateInterval configuration option.
Then, after calling
fixedUpdate: required number of times, Cocos2D calls the
update: method, but only once.
In this case, the
delta parameter of the
update: method contains the actual time passed since the last time it was called.
Should I just always use fixedUpdate: ?
After learning about the
fixedUpdate: method you can think that you should just always use the
fixedUpdate: method. This is not entirely true.
If you’re moving non-physics objects, updating label text or your UI then there is no reason to put this code in
fixedUpdate:. Otherwise you might just perform unnecessary work between the frames, by executing this code several times, when it can be executed only once, right before rendering.
However, if you’re detecting collisions, working with physics objects (your own implementation or using physics engine) you should always use
If you want to learn more about game development with Cocos2D v3 you can read my upcoming book, which will be published in a few days.
Also, you can find information about implementing fixed time step in this great article.
Thanks for reading!