Matter.js Sleeping Objects Optimization Explained
Matter.js incorporates a body sleeping system designed to drastically reduce CPU overhead in physics simulations containing numerous stationary or settled entities. This article explores how Matter.js detects inactive bodies, removes them from expensive computational pipelines like narrowphase collision resolution, wakes them upon dynamic interaction, and provides the configuration parameters developers need to fine-tune this optimization.
What is Sleeping in Matter.js?
In standard physics simulations, the engine continuously calculates gravity, velocity, and potential collisions for every active body in the world, even if that body is resting on the floor. For scenes with hundreds of stacked or settled objects, these calculations cause noticeable frame-rate drops.
The "sleeping" state is an optimization pattern where Matter.js temporarily deactivates computational updates for bodies that have come to a complete rest. When a body goes to sleep, the engine skips its motion integration, constraint solving, and detailed collision detection until an external event forces it to move again.
How Matter.js Determines When a Body Sleeps
Matter.js monitors the kinetic energy of each dynamic body across successive simulation ticks. It determines sleep eligibility using three primary factors:
Motion Calculation: Each frame, Matter.js calculates a smoothed motion value based on the body's linear and angular velocity: \[\text{motion} = \text{speed}^2 + \text{angularSpeed}^2\] This value is smoothed over time to prevent bodies from sleeping prematurely during momentary stops (such as the peak of an arc).
The Motion Threshold: A body must maintain a motion value below a predefined minimum threshold (internally tracked via
body.motion).The Sleep Counter: If a body remains below the threshold, its internal sleep counter increments each frame. Once this counter exceeds the
sleepThreshold(default is 60 ticks, approximately one second at 60 FPS), the engine marksbody.isSleeping = true.
Computational Savings During the Sleep State
Once a body is marked as sleeping, Matter.js bypasses several expensive physics pipeline steps:
- Broadphase and Narrowphase Collision: While sleeping bodies remain in the broadphase collision tree (like the Spatial Hash Grid or BVH), pairs composed entirely of sleeping bodies are discarded immediately. Narrowphase SAT (Separating Axis Theorem) checks are completely skipped between sleeping objects.
- Position and Velocity Integration: The engine bypasses numerical integration steps for sleeping bodies, avoiding redundant vector mathematics.
- Solver Iterations: Sleeping bodies are omitted from constraint and contact resolution loops, reducing the workload of the iterative solver.
How Sleeping Bodies Wake Up
Sleeping bodies do not remain dormant permanently. Matter.js
automatically transitions a body back to an awake state
(body.isSleeping = false) when:
- An active, awake body collides with it.
- A constraint (spring, rope, or joint) connected to the sleeping body experiences force from an awake body.
- The body is manually manipulated via code (such as modifying its
position, angle, velocity, or applying a force using
Body.applyForce). - The body is clicked or dragged using a
MouseConstraint.
When an awake body collides with a sleeping body, the wake signal cascades through adjacent sleeping bodies, preventing unnatural behavior like objects hanging in mid-air when their support is knocked away.
Enabling and Configuring Sleeping
Sleeping is disabled by default in Matter.js to prioritize
predictable behavior out of the box. To activate it, set
enableSleeping to true when initializing the
engine:
const engine = Engine.create({
enableSleeping: true
});You can customize the sensitivity on individual bodies or globally:
sleepThreshold: The number of idle updates required before a body falls asleep (default is60). Lower values put objects to sleep faster to save performance, but may cause objects to freeze unnaturally mid-motion.body.isSleeping: A boolean flag you can directly read or set to manually control a body's state usingSleeping.set(body, true)orSleeping.set(body, false).