Export Matter.js World to JSON
Exporting the current state of a Matter.js world to a JSON format is
possible, but it cannot be achieved using a standard
JSON.stringify() call directly on the engine or world
object. Because Matter.js instances contain complex internal structures
and circular references between bodies, constraints, and composite
hierarchies, direct serialization throws a circular structure error. To
export your simulation's state, you must selectively extract and
serialize the essential physical properties of your bodies and
constraints into a clean data structure.
Why Direct Serialization Fails
A Matter.js World or Engine contains deeply
nested references. For example, a Body references its
parent body, parts, vertices, and any Constraint attached
to it, while constraints simultaneously reference the bodies they
connect. Attempting to run JSON.stringify(engine.world)
will immediately trigger a
TypeError: Converting circular structure to JSON.
How to Export World State
To successfully save the world state to JSON, you need to map over the world's composite elements—specifically bodies and constraints—and extract only the state variables required to represent or restore them.
1. Extracting Body Data
For each body in Composite.allBodies(engine.world),
collect properties such as:
- Identities & Types:
id,label,isStatic - Transform:
position(x,y),angle - Motion:
velocity(x,y),angularVelocity - Geometry & Physics:
vertices(relative or absolute coordinates),mass,friction,restitution
2. Extracting Constraint Data
For each constraint in
Composite.allConstraints(engine.world), record:
- Connections:
bodyA.id,bodyB.id(save references via ID rather than the body object itself) - Offsets:
pointA,pointB - Properties:
length,stiffness,damping
Example Export Implementation
function exportWorldToJson(engine) {
const bodies = Matter.Composite.allBodies(engine.world).map(body => ({
id: body.id,
label: body.label,
isStatic: body.isStatic,
position: { x: body.position.x, y: body.position.y },
velocity: { x: body.velocity.x, y: body.velocity.y },
angle: body.angle,
angularVelocity: body.angularVelocity,
vertices: body.vertices.map(v => ({ x: v.x, y: v.y }))
}));
const constraints = Matter.Composite.allConstraints(engine.world).map(constraint => ({
id: constraint.id,
label: constraint.label,
bodyAId: constraint.bodyA ? constraint.bodyA.id : null,
bodyBId: constraint.bodyB ? constraint.bodyB.id : null,
pointA: constraint.pointA,
pointB: constraint.pointB,
length: constraint.length,
stiffness: constraint.stiffness
}));
const worldState = {
gravity: {
x: engine.gravity.x,
y: engine.gravity.y,
scale: engine.gravity.scale
},
bodies,
constraints
};
return JSON.stringify(worldState, null, 2);
}Restoring State from JSON
To load the exported JSON back into Matter.js:
- Parse the JSON string using
JSON.parse(). - Clear the active engine world using
Composite.clear(engine.world, false). - Recreate the bodies using
Bodies.fromVertices()or standard primitives (Bodies.rectangle,Bodies.circle), assigning the stored dynamic properties (velocity,angle,isStatic). - Rebuild constraints by matching the saved
bodyAIdandbodyBIdto the newly instantiated bodies. - Add the restored elements back into the world using
Composite.add().