menu_bookDocumentation

FixedUpdate Internals: Step Counting, Spiral of Death Prevention, Time.Scope, and ApplyForce vs ApplyImpulse

calendar_today May 4, 2026 schedule ~2 min read person patrickjr verified 50

FixedUpdate Internals: How the Fixed Timestep Works in s&box

The s&box fixed update system uses a step-counting approach rather than accumulating time. This is important to understand when debugging physics or timing issues.

How It Works

The FixedUpdate class tracks a _step counter. Each frame:

  1. curStep = floor( time / delta ) — compute the expected step count at the current time
  2. _step is clamped to [curStep - maxSteps, curStep] — prevents spiral of death
  3. While _step < curStep, increment _step and call fixedUpdate() with the correct time scope
CSHARP
internal void Run( Action fixedUpdate, double time, int maxSteps )
{
    var delta = Delta;
    long curStep = (long)Math.Floor( time / delta );

    // Clamp to prevent spiral of death
    _step = long.Clamp( _step, curStep - maxSteps, curStep );

    while ( _step < curStep )
    {
        _step++;
        using var timeScope = Time.Scope( (_step * delta), delta );
        fixedUpdate();
    }
}

Key Behaviors

Time.Scope

Time.Scope is used throughout the engine to temporarily override Time.Now and Time.Delta:
CSHARP
using var timeScope = Time.Scope( simulationTime, deltaTime );
// Inside this scope, Time.Now == simulationTime, Time.Delta == deltaTime

This is also used by Scene.Push() to restore the previous scene's time when switching between scenes.

Practical Implications

Was this helpful?