Matter.js collisionStart vs collisionActive vs collisionEnd

In Matter.js, managing physical interactions relies on tracking the lifecycle of collisions between rigid bodies. The engine exposes three primary collision events—collisionStart, collisionActive, and collisionEnd—which trigger at distinct phases of an interaction: the initial impact, ongoing contact across consecutive frames, and the eventual separation of the bodies. Understanding the timing and behavior of these events is essential for implementing gameplay mechanics such as jumping, dealing damage, and triggering visual effects.

The Collision Lifecycle

During each physics update (tick), the Matter.js engine checks for overlaps between bodies. Based on whether an overlap is new, ongoing, or finished, the engine dispatches one of three events via the Matter.Events module.

1. collisionStart

The collisionStart event fires only on the exact tick where two bodies first make contact. If two bodies collide and remain touching for multiple seconds, this event still only triggers once at the very beginning.

2. collisionActive

The collisionActive event fires on every frame that two bodies remain in physical contact after the initial collision has been registered. As long as the overlapping state persists from frame to frame, the engine will trigger this event on every tick.

3. collisionEnd

The collisionEnd event fires on the first frame where two bodies are no longer colliding. It signals that contact has broken, either because one body moved away, fell off, or was removed from the simulation.

Event Data Structure

All three events pass an event object containing a pairs array. Each entry in pairs represents a colliding pair of bodies (pair.bodyA and pair.bodyB) along with collision metadata, such as collision depth and normal vectors.

// Example usage across all three events
Matter.Events.on(engine, 'collisionStart', (event) => {
    event.pairs.forEach((pair) => {
        // Handle initial impact
    });
});

Matter.Events.on(engine, 'collisionActive', (event) => {
    event.pairs.forEach((pair) => {
        // Handle sustained contact
    });
});

Matter.Events.on(engine, 'collisionEnd', (event) => {
    event.pairs.forEach((pair) => {
        // Handle separation
    });
});

Summary Comparison

Feature collisionStart collisionActive collisionEnd
Trigger Point Frame contact begins Every frame contact continues Frame contact stops
Execution Rate Single execution Repeated every tick Single execution
Primary Focus Impact & initialization Sustained state & tracking Cleanup & detachment