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