Quick answer: Frame-rate dependent physics bugs happen when game code ties physics calculations to the render frame rate instead of using a fixed timestep. The fix involves moving all physics logic into fixed update loops, using interpolation for smooth rendering, enabling continuous collision detection for fast-moving objects, and testing at multiple frame rates throughout development.

A player with a 240 Hz monitor reports that their character falls through the floor. Another player at 60 FPS has never seen the issue. A speedrunner discovers that jump height changes depending on frame rate. These are physics bugs that only appear at high frame rates, and they are among the most difficult bugs to debug in game development — because the developer’s own machine often cannot reproduce them. Understanding why physics behaves differently at different frame rates is the first step toward eliminating an entire category of bugs from your game.

Why Frame Rate Affects Physics

Game physics simulations are numerical approximations. Instead of solving continuous equations of motion, the engine steps forward in small increments, calculating new positions and velocities at each tick. The size of that increment — the time step — determines the accuracy of the simulation.

When physics runs once per rendered frame, the time step equals the frame duration. At 60 FPS, each step is approximately 16.67 milliseconds. At 240 FPS, each step is approximately 4.17 milliseconds. At 30 FPS, it is 33.33 milliseconds. The physics equations produce different results at different step sizes because numerical integration is not perfectly linear. Small errors accumulate differently depending on how many steps you take to cover the same real-time duration.

This is not a bug in the physics engine. It is a fundamental property of discrete simulation. The solution is to decouple physics from rendering by running physics at a fixed rate regardless of how fast frames are drawn.

The Tunneling Problem

Tunneling is the most dramatic frame-rate dependent physics bug. A fast-moving object passes completely through a wall or floor because the collision detection system checks for overlap at each physics step, but the object moves far enough between steps to skip past the collider entirely.

At 60 FPS with a variable timestep, a bullet moving at 500 units per second travels approximately 8.3 units per frame. If the wall is 1 unit thick, the bullet easily clears it in a single step. At 240 FPS, the same bullet moves only 2.08 units per frame, which is more likely to be caught by the collision system. Paradoxically, higher frame rates can reduce tunneling — but the bug still exists and will surface on lower-spec hardware.

The fix depends on your engine. In Unity, enable Continuous Collision Detection on the Rigidbody component for fast-moving objects. This tells the physics engine to sweep the object’s path between frames rather than only checking its position at each step. In Godot, use the continuous_cd property on RigidBody3D nodes. In Unreal, set the collision mode to CCD (Continuous Collision Detection) on the relevant physics bodies.

Continuous collision detection is more expensive than discrete detection, so apply it selectively. Bullets, fast-moving projectiles, and the player character typically need it. Slow-moving environmental objects do not.

Jitter and Micro-Stuttering

Physics jitter manifests as objects vibrating in place, characters stuttering while moving, or cameras shaking subtly during smooth motion. It happens when physics and rendering run at different rates without proper interpolation.

Consider what happens when physics runs at a fixed 50 Hz but the game renders at 144 FPS. Physics updates every 20 milliseconds, but frames are drawn every 6.94 milliseconds. Between physics updates, the renderer draws two or three frames showing the object at the same position, then the physics update moves it, and the next few frames show the new position. The result is visible stutter even though the frame rate is high.

The solution is interpolation. After the physics step, calculate where the object should appear based on how far the renderer is between physics steps. If the current render time is 70% of the way from the last physics step to the next, draw the object at 70% of the distance between its last physics position and its current one.

In Unity, the physics system handles this automatically when you use Rigidbody components with the Interpolate option set to Interpolate or Extrapolate. In Godot 4.x, physics interpolation is available through the physics/common/physics_interpolation project setting. In Unreal, the Character Movement Component includes built-in interpolation. If you are writing custom movement code in any engine, you must implement interpolation yourself or accept visible jitter at mismatched frame rates.

Delta Time Mistakes

The most common source of frame-rate dependent physics is incorrect use of delta time. Delta time — the duration of the previous frame — is essential for frame-rate independent rendering, but using it for physics introduces subtle bugs.

A typical mistake looks like this: velocity += gravity * delta in the rendering update function instead of the physics update function. At 60 FPS, gravity applies 60 times per second with a delta of 0.0167. At 240 FPS, it applies 240 times per second with a delta of 0.00417. Mathematically, these should produce the same result if gravity is a constant acceleration. In practice, floating-point precision means the results diverge slightly, and that divergence compounds over time.

The rule is simple: all physics calculations belong in the fixed update loop. In Unity, use FixedUpdate() instead of Update(). In Godot, use _physics_process(delta) instead of _process(delta). In Unreal, physics already runs at a fixed tick rate through the physics sub-stepping system. Never apply forces, impulses, or velocity changes in the variable-rate render loop.

A subtler mistake is using Time.deltaTime inside Unity’s FixedUpdate(). Unity helpfully returns Time.fixedDeltaTime when you access Time.deltaTime inside FixedUpdate(), but if you cache the delta value from Update() and use it later in FixedUpdate(), you get the wrong value. Always use the delta provided by the function you are currently in.

Testing at Multiple Frame Rates

You cannot find frame-rate dependent bugs without testing at different frame rates. This sounds obvious, but most developers test exclusively at their monitor’s native refresh rate. If that is 60 Hz, they never see the bugs that players on 144 Hz or 240 Hz monitors encounter.

Every engine provides a way to cap the frame rate for testing. In Unity, set Application.targetFrameRate in a startup script. In Godot, set Engine.max_fps in your project settings or from a debug menu. In Unreal, use the t.MaxFPS console command. Create a debug menu that lets you switch between 30, 60, 120, 144, and 240 FPS during gameplay so you can observe physics behavior at each rate.

Test with V-Sync both enabled and disabled. V-Sync caps the frame rate to the monitor’s refresh rate, which provides a stable delta time. With V-Sync off, the frame rate fluctuates wildly, producing variable delta times that stress physics calculations in ways that a steady frame rate does not. Many physics bugs only appear under variable frame rates, not at a consistently high rate.

Also test at very low frame rates. Set the cap to 15 or 20 FPS and play through your game. Low frame rates produce large delta values that amplify every frame-rate dependent calculation. If your game behaves correctly at both 15 FPS and 240 FPS, it will work at everything in between.

When you find a frame-rate dependent bug, log the frame rate at the time of the bug report. Bugnet captures performance metrics alongside crash data, which means you can filter bug reports by frame rate and identify clusters of issues that only appear above or below specific thresholds. This correlation is invaluable for prioritizing fixes.

Engine-Specific Solutions

Each major engine handles the physics-rendering split differently, and understanding your engine’s specific approach saves debugging time.

In Unity, the fixed timestep is configured in Edit > Project Settings > Time. The default is 0.02 seconds (50 Hz). For games with fast-moving objects, consider reducing this to 0.01 seconds (100 Hz), but be aware that doubling the physics rate doubles the CPU cost. Unity’s new ECS-based physics (Unity Physics and Havok) offer more control over sub-stepping and can be more deterministic than the legacy PhysX integration.

In Godot, the physics tick rate is controlled by physics/common/physics_ticks_per_second in Project Settings, defaulting to 60. Godot 4.x introduced physics interpolation, which you should enable for any 3D project. For 2D games, the impact of physics jitter is less visible, but interpolation still helps. Godot’s physics engine uses a fixed timestep internally, so as long as you keep physics code in _physics_process(), you avoid most frame-rate dependencies.

In Unreal, physics sub-stepping allows you to run multiple physics updates per frame when the frame rate drops below the target physics rate. Enable it in Project Settings > Physics > Substepping. Set the Max Substep Delta Time to control the maximum physics step size. Unreal’s Chaos physics engine handles interpolation automatically for simulated bodies, but custom movement components need manual interpolation.

Determinism and Replays

Frame-rate dependent physics breaks determinism. If two players play the same input sequence at different frame rates and get different results, your physics is not deterministic. This matters for replays, netcode, and competitive fairness.

True physics determinism requires a fixed timestep, identical floating-point behavior across platforms, and no use of frame-rate dependent calculations anywhere in your simulation. This is extremely difficult to achieve in practice, especially across different CPU architectures that handle floating-point rounding differently.

For most games, approximate determinism is sufficient. Run physics at a fixed rate, avoid branching logic that depends on render frame timing, and accept that results may differ by small amounts across platforms. For competitive games that require exact determinism, consider integer-based physics or a deterministic math library that guarantees identical results regardless of platform.

Record physics state at fixed intervals during playtesting. Compare recordings from sessions at different frame rates. If the state diverges significantly after the same input sequence, you have a frame-rate dependency somewhere in your simulation. Binary search through your systems — disable half of them, check if the divergence persists, and narrow down the offending code.

Preventing Frame-Rate Dependent Bugs From Day One

The cheapest time to fix a frame-rate dependent physics bug is before it is written. Establish clear rules at the start of your project: all physics code goes in the fixed update loop, all movement uses the fixed delta, continuous collision detection is enabled for fast objects, and interpolation is turned on.

Add frame rate testing to your QA process. Before every release, run through your test suite at 30, 60, and 144+ FPS. Automate what you can — a CI script that boots the game at different frame rates and checks for physics errors is worth the setup time. For issues that slip through, structured crash reporting tells you which frame rate a player was running when the bug occurred, turning a “works on my machine” mystery into an actionable data point.

Document your physics architecture. Write down which update loop each system uses, what the fixed timestep is, and where interpolation is applied. When a new team member adds a feature, they need to know the rules. A physics bug introduced by well-meaning code in the wrong update function can take weeks to surface and hours to track down.

Set your game to 240 FPS and 15 FPS today. Play for five minutes at each. Whatever looks wrong is a bug your players already know about.