Monday, November 13, 2017

fixed timestep - How precise should timers in update loops be?


What is the suggestion of "enough precision" in a timer for a fixed game update loop? Currently I'm testing with this code, but it sometimes misses 1-2 updates @ 50hz. While at 30hz it seems to work perfect. 60hz again is even worse than 50hz. Is this because I have too low resolution on the timer? Is there something I'm missing?



Answer



There is a wrong assumption behind this question which leads to a solution that is not well prepared for real world requirements.


Don't ever count on a consistently stable frame time X, unless you are on a Real Time Operating System. The usual gaming platforms don't fall under this category. On all other systems the frame time is not deterministic (even if your update loop were deterministic, which it isn't either), it depends on variables that the game cannot control, the OS scheduler for one thing, other processes can kick in, energy saving settings and lots of other things.


Having that out of our way, the first and most important conclusion is: The game has to deal with a varying frame time. It might be 16 ms in one frame, and 27 ms in the next. The update loop simply has to deal with it. That rules out the fixed dt value in your code example.


So what is the solution?


Basically there is only one relyable and reasonable source of game time, the refresh rate of the graphics device. It does not make sense to update the game state with a higher frequency than the graphics card can render it. In fact that would introduce new problems without any reasonable gain.


However, it makes sense to update some subsystems with a higher frequency, as a physics engine for instance needs a stable simulation time. Most physics engines handle this theirselves by adding sub-steps/sub-loops, for instances bullets btDynamicsWorld::stepSimulation(btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) needs only be called once in your game loop and handles the necessary substeps itsself. The first parameter timeStep is the real dt since the last frame. The third parameter fixedTimeStep is the fixed simulation time, so it will step the simulation by adding substeps of fixedTimeStep until it hits the real frame time (timeStep) and even interpolates the physics state to the exact frame time. So that dirty work is off your shoulder unless you implement your own physics system.


So at the end it is much simpler and does not need any timers at all, except vsync to wait for the graphics cards swapping. Other than that, just measure the time since the last swap, that is the frame time to be passed to the game's subsystems.



No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...