Detect Collisions Without Physics in Matter.js
This article explains how to create a "ghost" or sensor body in
Matter.js that detects overlaps and triggers events without causing any
physical displacement, bouncing, or solid collision response. By setting
the isSensor property to true, you can easily
implement triggers, pickup zones, checkpoints, and vision cones in your
2D physics simulations.
The isSensor Property
Matter.js provides a built-in property for bodies called
isSensor. When a body is defined as a sensor, the physics
engine still registers and fires collision events for it, but completely
skips the collision resolution step. This means other rigid bodies will
pass straight through it instead of bouncing off or being blocked.
Creating a Ghost Body
You can enable this behavior by passing isSensor: true
in the body's options object during creation:
const { Bodies, World } = Matter;
// Create a static ghost/sensor body (e.g., a trigger zone or checkpoint)
const triggerZone = Bodies.rectangle(400, 300, 200, 100, {
isSensor: true,
isStatic: true,
render: {
fillStyle: 'rgba(0, 255, 0, 0.3)' // Semi-transparent visual
}
});
World.add(engine.world, triggerZone);You can also make dynamic (moving) bodies sensors using the same property:
const ghostBullet = Bodies.circle(100, 100, 10, {
isSensor: true
});Changing an Existing Body to a Sensor
If you have an existing body, you can toggle its sensor state dynamically at any point by modifying the property directly:
myBody.isSensor = true;Detecting Collisions with the Sensor
To detect when an object enters, remains within, or leaves the ghost
body, listen to the collision events provided by
Matter.Events:
const { Events } = Matter;
Events.on(engine, 'collisionStart', (event) => {
const pairs = event.pairs;
for (let i = 0; i < pairs.length; i++) {
const { bodyA, bodyB } = pairs[i];
// Check if one of the colliding bodies is our trigger zone
if (bodyA === triggerZone || bodyB === triggerZone) {
const otherBody = bodyA === triggerZone ? bodyB : bodyA;
console.log('Object entered the trigger zone:', otherBody);
}
}
});
Events.on(engine, 'collisionEnd', (event) => {
const pairs = event.pairs;
for (let i = 0; i < pairs.length; i++) {
const { bodyA, bodyB } = pairs[i];
if (bodyA === triggerZone || bodyB === triggerZone) {
const otherBody = bodyA === triggerZone ? bodyB : bodyA;
console.log('Object left the trigger zone:', otherBody);
}
}
});Difference
Between isSensor and collisionFilter
Matter.js also allows you to control collisions using
collisionFilter masks and categories. However, setting
collision filters to avoid collisions will prevent the engine from
generating collision events entirely. Use isSensor: true
when you still need to capture overlap events via code while bypassing
physical forces.