Prevent Exploding Overlapping Bodies in Matter.js

When rigid bodies inadvertently spawn or move inside one another in Matter.js, the physics engine attempts to resolve the overlap instantly, causing an unnatural, explosive ejection known as tunneling or separation impulse spikes. This article covers the primary methods to prevent these explosive physics reactions, including adjusting solver iterations, manipulating collision filtering during spawn routines, gradually expanding geometry, and clamping correction velocities.

Increase Engine Solver Iterations

The Matter.js engine resolves collisions using discrete iterations for position and velocity. When bodies overlap deeply, low iteration counts force the engine to correct large penetration depths in a single step, transferring immense kinetic energy to both bodies.

Increasing positionIterations and velocityIterations divides the correction work across smaller increments, yielding smoother separation:

const engine = Matter.Engine.create({
  positionIterations: 10, // Default is 6
  velocityIterations: 8   // Default is 4
});

While increasing iterations introduces a slight performance cost, it drastically reduces violent displacement for moderately overlapping objects.

Temporarily Disable Collisions via Sensors

The cleanest way to prevent an explosion during object creation is to spawn bodies as non-colliding entities and enable physical collision only after they are clear of other bodies.

Set isSensor: true on the body definition during creation:

const body = Matter.Bodies.circle(x, y, radius, {
  isSensor: true
});

Listen to the engine's collisionEnd or afterUpdate events. Once the body is no longer overlapping its neighbors (checked using Matter.Query.collides(body, otherBodies)), set body.isSensor = false.

Scale Bodies Up from Zero

Spawning an object at full size inside another object immediately triggers deep penetration algorithms. A reliable visual and mechanical workaround is to spawn the body at a negligible size and smoothly scale it to its intended size over a few frames.

const body = Matter.Bodies.circle(x, y, 1);
Matter.World.add(world, body);

let currentScale = 0.05;
const targetScale = 1.0;

Matter.Events.on(engine, 'beforeUpdate', () => {
  if (currentScale < targetScale) {
    const scaleFactor = 1.1;
    Matter.Body.scale(body, scaleFactor, scaleFactor);
    currentScale *= scaleFactor;
  }
});

Scaling the body outward pushes surrounding geometry away gradually rather than applying an instantaneous impulse.

Clamp Linear and Angular Velocity

If overlapping cannot be prevented before collision resolution takes place, you can artificially limit the speed at which bodies are allowed to separate. By clamping the maximum velocity on the engine's afterUpdate event, you absorb the explosive force before it renders to the screen.

const MAX_SPEED = 12;

Matter.Events.on(engine, 'afterUpdate', () => {
  const bodies = Matter.Composite.allBodies(engine.world);

  bodies.forEach(body => {
    if (body.speed > MAX_SPEED) {
      Matter.Body.setSpeed(body, MAX_SPEED);
    }
  });
});

Zero Restitution and Maximize Friction

Bounciness (restitution) acts as a force multiplier when overlapping bodies resolve. When resolving deep penetration, a high restitution value causes bodies to ricochet violently.

To mitigate this, set the restitution of volatile or newly spawned bodies to 0 and increase their frictionAir (e.g., 0.05 to 0.1). This absorbs momentum directly at the point of separation, allowing objects to slide apart gently rather than catapulting across the canvas.