Physics World

jolt_update

Advances the managed world with a fixed timestep and bounded catch-up.

jolt_update() converts frame time into zero or more fixed simulation steps. The accumulator makes simulation timing independent of render-frame timing, while max_frame_time and max_steps prevent an unbounded catch-up spiral.

Syntax#

Syntax
jolt_update([dt]);
ArgumentTypeDescription
dtReal | undefinedOPTIONAL. Frame duration in seconds. Defaults to undefined, using delta_time / 1,000,000.

Returns#

Real. Number of fixed steps processed, including 0. -1 indicates an invalid operation or simulation failure; read jolt_get_error() immediately.

Typical Step event#

GML
// Step event of the physics controller.
var steps = jolt_update();
if (steps < 0) {
    show_debug_message(jolt_get_error().message);
}

// Physics transforms and current-frame contacts are now ready.
player_body.sync();
var contacts = jolt_get_collisions();

Frame time input#

CallTime source
jolt_update()GameMaker delta_time converted from microseconds to seconds.
jolt_update(seconds)Explicit non-negative number of seconds.
Any negative argumentSelects automatic delta_time behaviour.

Fixed-step algorithm#

  • The supplied frame time is clamped to max_frame_time before being added to the accumulator.
  • While the accumulator contains at least fixed_dt, the world advances by exactly fixed_dt.
  • At most max_steps are performed in one call.
  • Each successful step subtracts fixed_dt and increments the lifetime simulation-step counter.
  • If max_steps is reached with more full steps pending, excess backlog is discarded while the fractional remainder is retained.
  • Contacts and character contacts are drained after stepping, including calls that perform zero steps.

Default timing#

SettingDefaultEffect
fixed_dt1 / 60 s60 physics steps per simulated second.
max_frame_time0.25 sAt most a quarter-second enters the accumulator per update.
max_steps8At most eight fixed steps are processed per call.

Catch-up example#

GML
// With fixed_dt = 1/60 and an explicit 0.05 second frame:
var steps = jolt_update(0.05);
// Normally processes 3 fixed steps, subject to accumulated remainder.

Per-step processing#

Before each world step the high-level character state is prepared. The native world advances CharacterVirtual controllers and then calls the Jolt rigid-body update. Afterwards the wrapper updates managed character state. Once all steps finish, collision queues are mapped to world and per-body event arrays.

Reading current state#

GML
var total_steps = jolt_get_simulation_steps();
var fixed_seconds = jolt_fixed_timestep();
var world_events = jolt_get_collisions();
var dropped = jolt_get_dropped_collision_count();

Read transforms, sync bound instances, and consume contact arrays after jolt_update(). Per-body and world collision lists represent the latest drain and are replaced by a later update.

Collision substeps#

The low-level convenience jolt_step() chooses collision_steps as ceil(delta_time × 60), clamped from 1 to 64. With the default fixed_dt of 1/60 this is one collision step per fixed update.

Low-Level / Advanced API#

GML
jolt_step(world, delta_time)
jolt_world_step(world, delta_time, collision_steps=1)

Low-level stepping requires a live world, finite delta_time greater than 0, and collision_steps from 1 through 64. It does not provide the managed accumulator, frame clamp, catch-up limit, high-level error context, or automatic collision-array mapping.

Verified operation contracts#

These contracts distinguish units, return values, errors and lifetime according to the current implementation. Check results: false, 0 and undefined can mean different things for different methods.

Symbol / ownerSignatureOperation contract
jolt_fixed_timestepjolt_fixed_timestep()Reads managed state without stepping: started Boolean / world handle / fixed_dt s / cumulative step count / valid body-wrapper count. Wrapper count is not a validation of every native handle.
jolt_get_simulation_stepsjolt_get_simulation_steps()Reads managed state without stepping: started Boolean / world handle / fixed_dt s / cumulative step count / valid body-wrapper count. Wrapper count is not a validation of every native handle.
jolt_is_startedjolt_is_started()Reads managed state without stepping: started Boolean / world handle / fixed_dt s / cumulative step count / valid body-wrapper count. Wrapper count is not a validation of every native handle.
jolt_updatejolt_update(frame_seconds = -1.0)Returns completed fixed-step count, -1 on error. Omitted/negative argument uses delta_time microseconds → seconds; caps input with max_frame_time/max_steps, drops excess backlog. Call once per frame; includes managed pre/post systems and contact draining.