Create Matter.js Plugins with Matter.Plugin.register

This guide demonstrates how to use Matter.Plugin.register to build, structure, and distribute reusable community extensions for the Matter.js 2D physics engine. You will learn the required plugin schema, how to safely hook into Matter.js lifecycle methods using internal utilities, and how to activate and publish your extension for other developers to integrate seamlessly into their projects.

The Plugin Object Specification

To create a plugin compatible with the Matter.js module system, you must define an object that conforms to the plugin interface. This object requires standard metadata properties and an install method:

Registering the Plugin

Call Matter.Plugin.register to register your plugin definition with the global Matter.js plugin registry. This step validates the plugin object and makes it accessible via Matter.use().

import Matter from 'matter-js';

const MatterAttractor = {
  name: 'matter-attractor',
  version: '1.0.0',
  for: 'matter-js@^0.19.0',

  install(base) {
    // Extend or patch Matter.js modules here
    base.Body.setAttractor = function(body, attractor) {
      body.attractor = attractor;
    };

    // Hook into the engine update loop
    base.after('Engine.update', function() {
      // Access the engine instance via 'this'
      const engine = this;
      const world = engine.world;
      const bodies = base.Composite.allBodies(world);

      for (let i = 0; i < bodies.length; i++) {
        if (bodies[i].attractor) {
          bodies[i].attractor(bodies[i]);
        }
      }
    });
  }
};

// Register the extension
Matter.Plugin.register(MatterAttractor);

export default MatterAttractor;

Hooking into Matter.js Methods

Avoid directly overriding methods on the core namespace to prevent breaking compatibility with other plugins. Instead, use Matter's built-in event-chaining hooks: base.before and base.after.

Inside these callbacks, this refers to the instance of the object executing the function (such as the specific Engine or Runner), and arguments passed to the original function are forwarded to your callback.

Consuming the Plugin

Once a plugin is registered, end users can activate it using Matter.use():

import Matter from 'matter-js';
import MatterAttractor from 'matter-attractor';

// Activate via the plugin object or registered name
Matter.use(MatterAttractor);
// Alternatively: Matter.use('matter-attractor');

// The extension's methods are now available
const engine = Matter.Engine.create();
const body = Matter.Bodies.circle(100, 100, 20);

Matter.Body.setAttractor(body, (b) => {
  // Custom attractor logic
});

Matter.use resolves dependencies defined in the uses array, prevents duplicate installations, and checks version constraints set in the for field.

Packaging for the Community

When preparing your extension for distribution via npm:

  1. Set the peerDependencies in your package.json to include matter-js.
  2. Register the plugin automatically when the script is imported, but also export the plugin object as the default export.
  3. Support both CommonJS and ES module environments using standard bundlers (like Rollup or Vite) to ensure compatibility across Node.js and browser-based build pipelines.