How to Clone an Existing Body in Matter.js

Cloning a body in Matter.js is essential when duplicating dynamic game elements, generating particle effects, or spawning recurring obstacles. Because the engine does not provide a native Body.clone() method, developers must instantiate a new body by copying the structural, physical, and rendering properties of the original. This guide demonstrates how to properly duplicate an existing body without causing identity conflicts or physics calculation errors.

Why Native Cloning Methods Fail

Directly copying a body object using Object.assign() or standard deep-clone utilities can break the physics simulation. Matter.js bodies contain internal state trackers, such as unique id values, computed geometric bounds, axes, and collision caches. If two bodies share identical internal IDs or reference identical vertex arrays, collision detection and constraint solving will fail. The safest approach is constructing a new body with Matter.Body.create() while reusing the original body's vertices and physical options.

Step-by-Step Cloning Function

To clone a body reliably, create a utility function that extracts the physical properties and clones the vertices to break memory references.

function cloneBody(originalBody, newX, newY) {
  // 1. Clone vertices to prevent reference sharing
  const vertices = Matter.Vertices.clone(originalBody.vertices);

  // 2. Clone basic physical properties and collision settings
  const options = {
    angle: originalBody.angle,
    friction: originalBody.friction,
    frictionAir: originalBody.frictionAir,
    frictionStatic: originalBody.frictionStatic,
    restitution: originalBody.restitution,
    density: originalBody.density,
    isStatic: originalBody.isStatic,
    isSensor: originalBody.isSensor,
    collisionFilter: {
      category: originalBody.collisionFilter.category,
      mask: originalBody.collisionFilter.mask,
      group: originalBody.collisionFilter.group
    },
    render: {
      visible: originalBody.render.visible,
      opacity: originalBody.render.opacity,
      strokeStyle: originalBody.render.strokeStyle,
      fillStyle: originalBody.render.fillStyle,
      lineWidth: originalBody.render.lineWidth,
      sprite: originalBody.render.sprite ? { ...originalBody.render.sprite } : null
    }
  };

  // 3. Create a fresh body instance
  const newBody = Matter.Body.create(options);

  // 4. Assign cloned vertices to restore the original shape
  Matter.Body.setVertices(newBody, vertices);

  // 5. Position the cloned body (using original coordinates if none are provided)
  const targetX = newX !== undefined ? newX : originalBody.position.x;
  const targetY = newY !== undefined ? newY : originalBody.position.y;
  Matter.Body.setPosition(newBody, { x: targetX, y: targetY });

  return newBody;
}

Adding the Cloned Body to the World

After generating the cloned body, add it to your engine's world composite. You can place it directly at an offset position to prevent it from immediately overlapping and colliding with the source body.

// Existing source body
const originalBox = Matter.Bodies.rectangle(200, 200, 80, 80, {
  restitution: 0.8,
  render: { fillStyle: '#e74c3c' }
});
Matter.Composite.add(engine.world, originalBox);

// Create a clone positioned 100 pixels to the right
const clonedBox = cloneBody(originalBox, 300, 200);

// Add the clone to the simulation
Matter.Composite.add(engine.world, clonedBox);

Handling Compound Bodies

If the target body is a compound body consisting of multiple sub-parts, you must iterate over the parts array:

  1. Skip the first part (originalBody.parts[0]), which represents the parent container.
  2. Clone each individual child part using its relative position and vertices.
  3. Pass the newly cloned parts to Matter.Body.setParts(newBody, clonedParts).