How to Stop Bodies Passing Through in Matter.js

In 2D physics simulations built with Matter.js, fast-moving objects or thin boundaries often cause "tunneling," an artifact where rigid bodies pass straight through one another instead of colliding. This issue stems from discrete collision detection, which checks for intersections only at specific intervals rather than continuously. This guide outlines the most effective techniques to resolve tunneling in Matter.js, including adjusting engine solver iterations, implementing custom sub-stepping, increasing obstacle thickness, and clamping body velocities.

1. Increase Engine Solver Iterations

Matter.js uses iterative solvers to resolve collisions and constraints. By default, the engine runs a low number of iterations to conserve performance. Increasing these values makes collision resolution significantly more accurate and rigid.

Modify your engine's positionIterations and velocityIterations:

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

Raising these values forces the engine to spend more calculations resolving overlaps, preventing objects from sinking into or escaping through opposing surfaces.

2. Implement Sub-Stepping (Smaller Time Steps)

If an object moves faster than its own width in a single simulation frame, it will completely skip past a barrier without triggering a collision. The most reliable fix is to break the engine update into smaller, multiple sub-steps per frame.

Instead of running a single Matter.Engine.update per render tick, execute multiple updates with smaller delta values:

const subSteps = 4;
const delta = 1000 / 60; // 60 FPS standard delta

function gameLoop() {
  const subDelta = delta / subSteps;

  for (let i = 0; i < subSteps; i++) {
    Matter.Engine.update(engine, subDelta);
  }

  requestAnimationFrame(gameLoop);
}

requestAnimationFrame(gameLoop);

Sub-stepping effectively reduces the distance a body travels between collision checks, virtually eliminating tunneling for fast-moving bodies.

3. Increase Boundary Thickness

Thin static bodies (such as lines or 1-pixel walls) are the most common victims of tunneling. A fast-moving body will easily step over thin barriers from one frame to the next.

4. Clamp Maximum Body Velocity

If sub-stepping is too computationally expensive for your target platform, you can enforce a terminal velocity on fast-moving bodies. This prevents objects from ever reaching a speed that allows them to skip boundaries.

Listen to the beforeUpdate event to constrain object speeds:

const MAX_SPEED = 15;

Matter.Events.on(engine, 'beforeUpdate', () => {
  const speed = Matter.Vector.magnitude(body.velocity);

  if (speed > MAX_SPEED) {
    const clampedVelocity = Matter.Vector.mult(
      Matter.Vector.normalise(body.velocity),
      MAX_SPEED
    );
    Matter.Body.setVelocity(body, clampedVelocity);
  }
});

Summary of Best Practices

To achieve stable collisions in Matter.js: