Update All Body Properties in a Matter.js Composite

This guide explains how to batch-update the physical properties of every physics body contained within a Matter.js Composite. By utilizing the built-in Composite.allBodies method, you can recursively find all top-level and nested bodies and apply new values for attributes such as friction, restitution, density, and static states.

Retrieving All Bodies in a Composite

A Composite in Matter.js can contain individual bodies as well as nested composites. Accessing composite.bodies directly only returns the top-level bodies, ignoring any sub-composites. To retrieve every body regardless of nesting depth, use Matter.Composite.allBodies():

const allBodies = Matter.Composite.allBodies(myComposite);

Iterating and Modifying Properties

Once you have the array of bodies, iterate through them using a loop or forEach and apply your changes.

When updating simple scalar values like friction or restitution (bounciness), you can update them directly on each body instance:

const allBodies = Matter.Composite.allBodies(myComposite);

allBodies.forEach(body => {
    body.friction = 0.05;
    body.frictionAir = 0.01;
    body.restitution = 0.8; // Bounciness
});

Modifying Properties Using Matter.Body Helper Methods

For properties that require internal calculations—such as mass, inertia, density, or static state—use the corresponding Matter.Body.set* methods instead of direct assignment. This ensures Matter.js automatically recalculates the physics constraints.

Setting Static State

To toggle whether all bodies in a composite are frozen in place:

allBodies.forEach(body => {
    Matter.Body.setStatic(body, true);
});

Updating Density and Mass

Modifying density requires recalculating mass and moment of inertia:

allBodies.forEach(body => {
    Matter.Body.setDensity(body, 0.005);
});

Updating Velocities

To impart forces, reset velocity, or stop all movement:

allBodies.forEach(body => {
    Matter.Body.setVelocity(body, { x: 0, y: 0 });
    Matter.Body.setAngularVelocity(body, 0);
});

Modifying Collision Filters

If you need to change how all bodies in the composite interact with other bodies in the simulation, update the collisionFilter property:

allBodies.forEach(body => {
    body.collisionFilter.category = 0x0002;
    body.collisionFilter.mask = 0x0001;
    body.collisionFilter.group = -1;
});

Reusable Utility Function

You can combine these approaches into a generic utility function that accepts a composite and a configuration object:

function updateCompositeProperties(composite, properties) {
    const bodies = Matter.Composite.allBodies(composite);

    bodies.forEach(body => {
        if (properties.isStatic !== undefined) {
            Matter.Body.setStatic(body, properties.isStatic);
        }
        if (properties.density !== undefined) {
            Matter.Body.setDensity(body, properties.density);
        }
        if (properties.friction !== undefined) {
            body.friction = properties.friction;
        }
        if (properties.restitution !== undefined) {
            body.restitution = properties.restitution;
        }
    });
}

// Example usage:
updateCompositeProperties(myComposite, {
    friction: 0.1,
    restitution: 0.9,
    isStatic: false
});