Replay: Box2D

kg1 pts0 comments

Replay :: Box2D

Jun 7, 2026

Replay

Replay is a new system I developed for Box2D. The main goal is to allow users to send me files I can use to reproduce bugs. Because Box2D is open source, I can rarely run a user’s game or see their code in full context. This makes it hard to track down problems. Previously in v2.4 a user could use b2World::Dump to save a text file that let me reproduce bugs. This file is just C++ code that would recreate the world using the standard definitions such as b2BodyDef. This worked quite well but the dump file had many limitations:

it didn’t include the internal state of Box2D

it didn’t include queries

it could not represent API calls to apply forces and impulses

I decided to build a new recording system that could faithfully capture a small simulation over a few seconds that could exactly reproduce what a user was seeing in their game.

Making a recording

I wanted recording to be easy for a game to implement. It involves just a few function calls.

int initialCapacity = 32 * 1024;<br>b2Recording* recording = b2CreateRecording( initialCapacity );<br>b2World_StartRecording( worldId, recording );

// ... run your game

b2World_StopRecording( worldId );

b2SaveRecordingToFile( recording, "my_recording.b2rec" );<br>b2DestroyRecording( recording );

Recording can start at any point in the simulation. When you start a recording it captures the initial state of the world. This copies all the internal data structures in Box2D. So you can start and stop the recording immediately to just capture the world state. But it is more useful to capture the simulation over time.

Once the recording is started, further Box2D operations are captured by just recording the function arguments. For example, if you call:

b2Body_ApplyLinearImpulse( bodyId, impulse, point, wake );

This will append an opcode and the function arguments to the recording.

Calls to b2World_Step follow the same process. This records an opcode, the time step, and the number of sub-steps. It also records a hash of the body transforms and velocities for validation of determinism.

Recording captures all body creation and destruction operations. It captures all the forces and impulses applied. It even captures all the ray casts and other queries. It should capture anything that modifies the world or things in the world.

The recording file is a header, followed by a full snapshot, followed by many opcodes and their arguments.

File Structure

The file is binary to keep it compact and fast. These files can get quite large, especially for large worlds. However, it is about as efficient as it can be while providing determinism.

Replay

The Box2D samples application has a sample that is the Replay Viewer. It gets special treatment in the samples app, including its own menu, outliner, and time scrubber.

Replay Viewer

The replay viewer creates and simulates a live b2World based on the recording. It loads the initial snapshot, then faithfully applies all recorded API calls, including stepping this world. This means you can view all simulation data, including contact points, contact and joint impulses, body velocities, and so on.

When you first load a recording it generates key frames. These key frames are full snapshots at evenly spaced time intervals across the full time span of your recording. The default is one key frame every 16 time steps. Generating key frames takes time and memory. You can set a memory budget in megabytes and the replay system will generate as many key frames as possible to live within that budget.

There are two benefits of this key frame system. First, more key frames at smaller intervals means scrubbing is faster, especially when there are many moving bodies. Second, run-time generation of key frames means they don&rsquo;t need to be stored in the recording. This keeps the file size under control.

In principle you could host replay in your own application using the Box2D API. But I don&rsquo;t expect this to be common. However, I encourage you to use the official replay viewer to help debug your game.

Queries

The recording and replay system can record queries, including their callback results. They can be viewed in the Replay Viewer. Queries are live. They perform the actual query as recorded, applying the recorded callback results. I expect this feature to be quite useful for debugging game code.

Query Replay

Snapshots

A highly requested feature of Box2D is rollback. The idea is that a game can take a snapshot of the world and then later reset to that snapshot to effectively rewind time. The replay system was not designed for this, but snapshots were needed to make replay work, so I&rsquo;m making them available in the API. Here&rsquo;s how they are used.

// First call gets the size, second fills the buffer.<br>int size = b2World_Snapshot( worldId, NULL, 0 );<br>uint8_t* image = malloc( size );<br>b2World_Snapshot( worldId, image, size );

// ... keep simulating ...

b2World_Restore(...

recording replay box2d time rsquo game

Related Articles