Extract Bodies from Nested Composites in Matter.js
In Matter.js, physics worlds and complex structures are organized
using the Composite module, which can contain bodies,
constraints, and other nested composites. When dealing with multi-level
hierarchies, retrieving every single rigid body requires traversing all
nested branches. This article explains how to efficiently extract all
bodies from a deeply nested composite using both the built-in Matter.js
API and a custom recursive approach.
Using the Built-In
Method: Composite.allBodies
The most straightforward way to extract all bodies from a nested
composite hierarchy is using the built-in
Matter.Composite.allBodies() method. This function
recursively searches the provided composite and all of its child
composites, returning a flat array containing every Body
object.
const { Composite } = Matter;
// Retrieve all bodies from a deeply nested composite (such as engine.world)
const allBodies = Composite.allBodies(rootComposite);
console.log(allBodies); // Returns a flat array of Body objectsComposite.allBodies() handles arbitrary levels of
nesting automatically, making it the recommended approach for standard
use cases.
Using a Custom Recursive Traversal
If you need to filter bodies during retrieval, track parent
relationships, or modify items during traversal, you can write a manual
recursive function. A composite stores its direct child bodies in the
bodies array and child composites in the
composites array.
function extractBodiesRecursively(composite, result = []) {
// Add bodies from the current composite level
if (composite.bodies && composite.bodies.length > 0) {
result.push(...composite.bodies);
}
// Recursively traverse any nested composites
if (composite.composites && composite.composites.length > 0) {
for (let i = 0; i < composite.composites.length; i++) {
extractBodiesRecursively(composite.composites[i], result);
}
}
return result;
}
// Usage
const extractedBodies = extractBodiesRecursively(rootComposite);Key Considerations
- Garbage Collection: Methods like
Composite.allBodies()allocate a new array every time they run. Avoid invoking this repeatedly inside a continuous 60 FPS update loop; instead, cache the array and refresh it only when composites are added or removed. - Mutations: The returned array is a flat reference
list. Removing an element from the returned array does not remove the
body from the physics simulation. To remove a body from the simulation,
pass it to
Matter.Composite.remove(composite, body).