0
\$\begingroup\$

Recently, I have started developing my game engine and I have been reading about game loops and the differences between Fixed TimeStep and Semi-Fixed Timestep. Both of them can be found around the web, but I will provide the most famous article: https://gafferongames.com/post/fix_your_timestep/

As a small reminder of both methods:

As far as I see it, Semi-Fixed timesteps fixes many of the issues with varying delta times between frames by implementing a while loop that consumes deltas in steps of a given size until the delta time for the frame is <= 0.0f. If the delta time is smaller than the step, the delta time is fed to the update function instead. This loop protects againsts changes in framerate, but, due to the delta time sent to the update not being always equal, it doesn't allow for a deterministic execution.

Fixed time step solves this by implementing an accumulator and only calling update when the accumulated delta time is bigger than the step value used by updates. I.e: If we have a step of 0.2 s of length, and the elapsed delta is 0.3 s, we do a step and store the 0.1 s remaining time for the next frame. Always updating by the same step allows for deterministic behaviour no matter the framerate.

On my engine, I implemented two different update methods that may be used to implement different behaviours: FixedUpdate() and Update(). Both methods follow the same rationale as the equally named ones from Unity Engine.

Implementing the fixed step loop was quite easy as I only had to stick to the basic theory. But when it came to writting the update method, I doubted between a simple Update call with the given delta time in this frame or a Semi-Fixed Step loop. Pseudocode below:

float FixedUpdateTimeStep = 1/60.0; // Fixed update called 60 times per second
float LastFrameTime = GetCurrentTime();
float TimeSinceLastFixedUpdate = 0.0;

while ( !quit )
{
    float CurrentTime = GetCurrentTime();
    float FrameTime = CurrentTime - LastFrameTime ;
    LastFrameTime = CurrentTime;
    TimeSinceLastFixedUpdate += FrameTime;

    // The article seems to use this branch at the end
    // to avoid adding deltas to big but I think this
    // will break determinism if the game was an online
    // one? Thinking of computer A and B and one of them
    // slowing down therefore not computing same deltas.
    //if ( FrameTime > MaxFrameTime )
    //    FrameTime = MaxFrameTime;

    // Fixed update.
    while ( TimeSinceLastFixedUpdate >= FixedUpdateTimeStep )
    {
        TimeSinceLastFixedUpdate -= FixedUpdateTimeStep;
        FixedUpdate(FixedUpdateTimeStep);
    }

    // Semi fixed update. Does this make sense or I should simply
    // call update with the given dt (maybe clamped to protect from
    // spikes) and avoid this extra loop.
    // calling update a single time is what unity does.
    while ( FrameTime > 0.0 )
    {
        // SemiFixedMaxDeltaStep may be the same value as the 
        // FixedUpdateTimeStep or another one.
        DeltaTime = min( FrameTime , SemiFixedMaxDeltaStep);
        Update(DeltaTime)
    }

As far as I see it, combining semi-fixed timesteps for the update method with fixed steps for the fixed update seems to defeat the purpose of the latter as the whole point of semi-fixed timesteps is to provide better resiliency for physics by setting an upper bound on the delta time, even if no determinism is achieved.

I think that I should simply stick to the Fixed Time Step for determinist behaviour and do a single call to the Update method per frame with the elapsed delta, whatever it may be. Maybe add a clamping to this last one to avoid very big delta times?

Thank you very much and hopefully I was clear enough!

\$\endgroup\$
  • 1
    \$\begingroup\$ It sounds like you've already reasoned through what makes sense for your engine. You do not need our permission or validation to proceed with this plan. \$\endgroup\$ – DMGregory Jan 5 at 18:08
  • \$\begingroup\$ I think I'm moving this direction then. I asked to see if somebody saw any errors in my conclusions just to get sure I was understanding the whole thing. Thanks for the reply. \$\endgroup\$ – Devem Jan 5 at 18:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.