Skip to main content

Serialization

When the serde-serialize feature of bevy_rapier is enabled, most data structures of Rapier become serializable using serde. Serialization can be useful to save the complete state of the simulation, e.g., to send it over the network, or to restore this state later.

The complete state of the simulation is serialized by serializing the components of its physics context: RapierContextSimulation, RapierContextColliders, RapierRigidBodySet, and RapierContextJoints all implement the Serialize and Deserialize traits of serde. The RapierContext structure given by the ReadRapierContext system parameter implements Serialize as well, so the four of them can be serialized at once. The RapierConfiguration component of the context implements these traits too, so it can be saved with them, as in the following example. Restoring a snapshot is done by inserting the deserialized components on the entity of the physics context, replacing the previous ones:

/// The components holding the complete state of the simulation of a physics context, and its
/// configuration.
type ContextComponents = (
RapierContextSimulation,
RapierContextColliders,
RapierRigidBodySet,
RapierContextJoints,
RapierConfiguration,
);

/// Serializes the default physics context when S is pressed.
fn save_snapshot(
mut commands: Commands,
keys: Res<ButtonInput<KeyCode>>,
context: Query<
(
&RapierContextSimulation,
&RapierContextColliders,
&RapierRigidBodySet,
&RapierContextJoints,
&RapierConfiguration,
),
With<DefaultRapierContext>,
>,
) {
if keys.just_pressed(KeyCode::KeyS) {
let components = context.single().unwrap();
let serialized =
bincode::serde::encode_to_vec(components, bincode::config::standard()).unwrap();
commands.insert_resource(Snapshot(serialized));
}
}

/// Restores the snapshot when R is pressed.
fn restore_snapshot(
mut commands: Commands,
keys: Res<ButtonInput<KeyCode>>,
snapshot: Option<Res<Snapshot>>,
context: Query<Entity, With<DefaultRapierContext>>,
) {
if let (true, Some(snapshot)) = (keys.just_pressed(KeyCode::KeyR), snapshot) {
// The maps from entities to handles are rebuilt automatically by the deserialization.
let (components, _): (ContextComponents, usize) =
bincode::serde::decode_from_slice(&snapshot.0, bincode::config::standard()).unwrap();
// Replace the components of the physics context by the deserialized ones.
commands.entity(context.single().unwrap()).insert(components);
}
}

Some parts of the physics context are skipped by the serialization: the PhysicsPipeline and the CollisionPipeline (which don't hold any useful state), the event handler installed with RapierContextSimulation::set_event_handler, the events not sent yet, and the step statistics. The maps from entities to handles aren't serialized either: they are rebuilt automatically when the components are deserialized, from the user-data of the Rapier objects (which contain the bits of their entity). If you restore the sets of a physics context in another way, call RapierContextColliders::rebuild_entity_maps, RapierRigidBodySet::rebuild_entity_maps, and RapierContextJoints::rebuild_entity_maps to rebuild them.

warning

The Rapier objects refer to their entities by their identifier. Therefore a deserialized physics context is only meaningful in a world where the same entities exist with the same identifiers (e.g. when restoring a snapshot of the same application). Note as well that the components of your entities (RigidBody, Collider, Transform, etc.), and the TimestepMode resource, are not part of the serialized components: they must be saved separately (the Collider component and the TimestepMode resource implement the traits of serde as well, whereas most of the other components can be serialized through the reflection of Bevy).

info

If the enhanced-determinism feature of Rapier is enabled, and if your platform fulfills the required determinism requirements, then you have the guarantee that running the exact same simulation on two different machine will result in the exact same byte vectors if the physics state is serialized on both machines after the same number of timesteps.