How to Listen for Engine Events in Matter.js
Matter.js provides a built-in event system that allows developers to
hook into the simulation lifecycle, monitor state updates, and detect
physical interactions. This guide covers how to use the
Matter.Events module to bind callbacks to the Matter.js
engine, detailing the most common engine events, their practical
applications, and clear code examples for implementation.
The Matter.Events.on
Method
To listen for events emitted by an engine instance, use the
Matter.Events.on function. This method registers a callback
function that triggers whenever the specified event occurs.
Matter.Events.on(engine, 'eventName', function(event) {
// Logic executed on event trigger
});The first argument is the target object emitting the event (the
engine), the second is a string representing the event
name, and the third is the callback function, which receives an
event object containing contextual data.
Essential Engine Events
The Matter.js Engine emits several lifecycle and
collision events throughout its update loop.
1. beforeUpdate
Fires just before the engine runs an update step. This is useful for applying custom forces, modifying velocities, or adjusting body properties before physics calculations occur.
Matter.Events.on(engine, 'beforeUpdate', function(event) {
// Apply a custom force to a body before the step calculates
Matter.Body.applyForce(myBody, myBody.position, { x: 0, y: -0.05 });
});2. afterUpdate
Fires immediately after the engine finishes an update step. Use this to synchronize external renderers, update non-physics game state, or read updated body coordinates.
Matter.Events.on(engine, 'afterUpdate', function(event) {
// Read the updated coordinates after physics calculations
console.log('Body position:', myBody.position.x, myBody.position.y);
});3. collisionStart
Fires when two or more bodies begin to collide during an update step.
The event object includes a pairs array
containing the collision details.
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;
console.log('Collision started between:', bodyA.label, bodyB.label);
}
});4. collisionActive
Fires during every update tick where two bodies remain in contact after the initial collision step.
Matter.Events.on(engine, 'collisionActive', function(event) {
event.pairs.forEach(pair => {
// Continuous contact handling (e.g., surface friction damage)
});
});5. collisionEnd
Fires when two bodies separate and the collision state terminates.
Matter.Events.on(engine, 'collisionEnd', function(event) {
event.pairs.forEach(pair => {
console.log('Collision ended between:', pair.bodyA.label, pair.bodyB.label);
});
});Unsubscribing from Events
To remove an active listener, use Matter.Events.off. You
must pass the target, the event name, and the exact reference to the
callback function that was registered.
function onUpdate(event) {
console.log('Engine updated');
}
// Subscribe
Matter.Events.on(engine, 'afterUpdate', onUpdate);
// Unsubscribe
Matter.Events.off(engine, 'afterUpdate', onUpdate);Passing only the target and the event name to
Matter.Events.off(engine, 'afterUpdate') will unbind all
listeners associated with that specific event.