Skip to main content

Fixed Substepping

Version Info

Added in v1.21.0. Enabled (ON) by default.

Fixed Substepping runs the entire simulation in fixed time-steps (FixedDt = 1 / TargetFramerate), stepping the solver as many times as needed per frame, to achieve stable physics that does not depend on the frame rate.

The Problem It Solves​

The legacy path integrated each frame directly with the actual DeltaTime, so changing the frame rate changed the way bones sway, how they converge, and how much they sag (e.g. the look does not match between 60 fps and 30 fps).

Integration error from gravity in particular is strongly affected by the frame rate, and normalizing damping alone could not resolve it. Fixed Substepping fundamentally solves this by running the whole solver at a fixed dt.

Setup​

This is a project-wide setting that you can change under Project Settings > Plugins > Kawaii Physics (see also Project Settings).

Use Fixed Substepping​

Enable fixed substepping - Runs the entire simulation in fixed time-step substeps, eliminating frame-rate-dependent behavior.

PropertyValue
Typebool
Defaulttrue
CategorySimulation

Max Substeps​

Maximum number of substeps - The maximum number of substeps per frame. This is an upper limit that prevents runaway behavior (spiral of death) during low fps or hitches; any time beyond this is discarded.

PropertyValue
Typeint32
Default4
Range1 - 16
CategorySimulation

How It Works​

The actual frame time DeltaTime is accumulated, and the solver is stepped as many times as needed at the fixed internal step FixedDt (the standard fixed-timestep accumulator pattern).

Accumulate the real time of the frame
↓
Split into FixedDt (= 1 / TargetFramerate) chunks
↓
Step the solver that many times (including collision, constraints, external forces)
↓
Carry the leftover time over to the next frame

Fixed Substepping concept

Real frame time is split into fixed-dt substeps. At 60fps and 30fps the same total simulated time is reached, so the swing looks consistent. (Diagram labels are in Japanese.)

  • FixedDt is derived from each node's Target Framerate (default 60, KawaiiPhysics category).
  • At low fps the substep count grows, so the CPU cost increases (up to Max Substeps times). Time beyond Max Substeps is discarded to prevent runaway after a hitch.
  • At high fps (DeltaTime < FixedDt), a frame may run zero substeps and hold the previous state.
Under the Hood

During substeps, the input animation pose target is interpolated with Lerp / Slerp, and wind/gravity/external forces are applied every substep. Wind scene queries are cached once per frame, preserving worker-thread safety.

Backward Compatibility​

Behavior change in v1.21.0

Fixed Substepping is enabled (ON) by default in v1.21.0. As a result, the way bones sway may change slightly compared to previous versions (it becomes more stable).

If you need exactly the same behavior as previous versions, turn Use Fixed Substepping OFF. When OFF, it runs with the legacy single-step integration path.

Checking Performance​

Measure the load from the increased substep count at low fps in the running environment. The statistics overlay and Unreal Insights use separate workflows.

stat Anim Statistics Overlay​

Run this command in the game or PIE console, then look for entries beginning with KawaiiPhysics_.

stat Anim

Unreal Insights Trace​

  1. Start a trace from the Trace / Insights status bar at the bottom of the editor.
  2. Reproduce the scenario you want to measure, then open the trace in Unreal Insights Session Browser.
  3. In Timing Insights, inspect the CPU track for animation processing time.

Setting Target Framerate higher than necessary increases the substep count and the load, so set a value appropriate for your target (60 in most cases).