Handling Extreme Mass Ratios in Matter.js
Simulating collisions between bodies with extreme mass ratios in Matter.js often leads to physical instability, such as violent jittering, tunneling, and explosive velocity spikes. This instability occurs because the engine's iterative impulse solver struggles to balance the disproportionate forces exchanged between massive and featherweight bodies within a single frame. Stabilizing these simulations requires tuning the engine’s solver settings, clamping mass values, implementing sub-stepping, and adjusting collision parameters to ensure predictable behavior.
Increase Solver Iterations
Matter.js defaults to low iteration counts to prioritize performance.
When bodies with vast mass differences interact, the default settings
cannot resolve the constraints before applying velocities. Increasing
the position and velocity iterations on your Engine
instance gives the solver more passes to settle overlapping bodies
accurately:
engine.positionIterations = 12; // Default is 6
engine.velocityIterations = 8; // Default is 4Raising these values provides immediate stability gains at the expense of a minor CPU performance hit.
Implement Sub-Stepping (Smaller Delta Times)
Extreme mass collisions transfer enormous momentum in a single step, causing lighter objects to launch across the scene or pass through geometry entirely. You can mitigate this by running smaller, multiple fixed time-steps per frame rather than a single large update:
const subSteps = 4;
const delta = (1000 / 60) / subSteps;
function updatePhysics() {
for (let i = 0; i < subSteps; i++) {
Engine.update(engine, delta);
}
}Dividing the delta reduces the impulse magnitude per step, allowing the solver to correct penetration gradually.
Clamp the Effective Mass Ratio
A realistic mass ratio (such as a 10,000 kg boulder hitting a 1 kg box) is rarely necessary to achieve the desired visual effect. In game physics, a ratio of 1:10 or 1:20 usually looks identical to an infinite difference to the human eye.
Instead of allowing dynamic bodies to retain extreme mass
calculations derived from density and area, manually set the mass using
Body.setMass:
const maxMassRatio = 20;
const clampedMass = Math.min(heavyBody.mass, lightBody.mass * maxMassRatio);
Body.setMass(heavyBody, clampedMass);Convert Immovable Massive Bodies to Static
If the heavier object should not respond to collisions at all (for
example, a wrecking ball, crusher, or moving platform), do not give it
an arbitrarily large dynamic mass. Instead, define it as a static body
(isStatic: true) and move it manually using
Body.setPosition or Body.setVelocity. Static
bodies have infinite mass in the solver and resolve collisions against
dynamic bodies in a single direction, eliminating oscillation.
Lower Restitution and Friction
Elastic collisions exacerbate instability when disparate masses collide. High restitution causes the lighter body to rebound with an amplified velocity that can easily break through boundary walls.
Set restitution (bounciness) to 0 or
near-zero on both interacting bodies:
body.restitution = 0;Additionally, reducing friction and
frictionStatic prevents high tangential forces from
imparting sudden, massive angular velocity to the lighter object.
Use Collision Slop and Chamfers
Matter.js includes a slop property on bodies that
dictates the allowable penetration threshold before the solver
aggressively pushes bodies apart. Increasing the slop on
extreme bodies prevents the engine from overcompensating for
micro-penetrations. Adding chamfered (beveled) edges to sharp polygon
vertices also prevents light objects from catching on corners and
accumulating erratic rotational torque.