How to Identify Colliding Bodies in Matter.js

This article explains how to determine which two physics bodies are involved in a collision using Matter.js. When a collision occurs, Matter.js fires collision events containing a list of contact pairs. By inspecting the bodyA and bodyB properties on each pair, along with labels or custom identifiers assigned to those bodies, you can reliably identify which objects interacted and execute game logic accordingly.

Listening to Collision Events

Matter.js provides three main collision events on the Engine instance: collisionStart, collisionActive, and collisionEnd. To inspect collisions, attach an event listener to the engine:

Matter.Events.on(engine, 'collisionStart', function(event) {
    const pairs = event.pairs;
    
    for (let i = 0; i < pairs.length; i++) {
        const bodyA = pairs[i].bodyA;
        const bodyB = pairs[i].bodyB;

        // Identification logic goes here
    }
});

The event.pairs array contains every distinct collision occurring in the current physics step. Each element in this array has two key properties: pair.bodyA and pair.bodyB.

Identifying Bodies Using Labels

The standard approach to distinguish bodies is assigning a string to the label property when creating the body:

const player = Matter.Bodies.rectangle(100, 100, 50, 50, { label: 'player' });
const ground = Matter.Bodies.rectangle(400, 600, 800, 50, { isStatic: true, label: 'ground' });

Because Matter.js does not guarantee the order of bodyA and bodyB, you must check both directions:

Matter.Events.on(engine, 'collisionStart', function(event) {
    event.pairs.forEach(pair => {
        const { bodyA, bodyB } = pair;

        if (
            (bodyA.label === 'player' && bodyB.label === 'ground') ||
            (bodyA.label === 'ground' && bodyB.label === 'player')
        ) {
            console.log('Player touched the ground');
        }
    });
});

Identifying Bodies Using Custom Properties or References

If your application requires more specific data than a string label, you can attach custom properties or direct references to the body object upon creation:

const bullet = Matter.Bodies.circle(200, 200, 5, {
    label: 'bullet',
    plugin: { damage: 25, ownerId: 'player1' }
});

Alternatively, compare object references directly if you hold a reference in scope:

if (bodyA === player || bodyB === player) {
    const otherBody = bodyA === player ? bodyB : bodyA;
    console.log('Player collided with:', otherBody.label);
}

A Clean Helper Pattern

To avoid repetitive conditional statements, use a helper function that sorts or matches the pair:

function checkCollision(pair, labelA, labelB) {
    return (
        (pair.bodyA.label === labelA && pair.bodyB.label === labelB) ||
        (pair.bodyA.label === labelB && pair.bodyB.label === labelA)
    );
}

// Usage inside the event listener:
if (checkCollision(pair, 'player', 'enemy')) {
    // Handle player-enemy interaction
}

Using consistent labels and accounting for variable body ordering ensures reliable collision resolution across all your Matter.js simulations.