How does planck.js handle continuous collision detection?
Planck.js, a 2D rigid-body physics engine written in pure JavaScript, prevents fast-moving objects from tunneling through geometry by implementing a specialized Continuous Collision Detection (CCD) system based on the original C++ Box2D architecture. In standard discrete physics simulations, objects move in discrete intervals, which can cause high-velocity bodies to completely bypass obstacles between frames. Planck.js solves this by calculating the precise trajectory over time, identifying separating axes, and applying a multi-step time-of-impact (TOI) sub-stepping solver that stops and processes collisions exactly when they occur.
The Problem of Tunneling in Discrete Stepping
In a standard discrete simulation, a physics engine advances time by fixed steps (\(\Delta t\)). It updates positions based on velocity and checks for overlaps only at those specific instants. If an object is small or traveling at an exceptionally high velocity, its displacement during a single \(\Delta t\) can exceed its own thickness or the thickness of the target geometry. As a result, the object is on one side of a wall in frame A and entirely on the other side in frame B. Discrete collision detection fails to see an overlap, allowing the object to “tunnel” through solid walls.
Time of Impact (TOI) Calculations and Sweeps
To prevent tunneling, planck.js employs a dedicated
TimeOfImpact function that evaluates the movement of shapes
continuously over a time step.
- The Sweep Structure: Instead of looking at static
final positions, the engine uses a
Sweepstructure. This structure encapsulates both the initial and final transforms (translation and rotation) of the two interacting shapes over the duration of the step. - Separating Axis Linearization: The
TimeOfImpactalgorithm utilizes a distance function to establish an initial separating axis between two moving shapes. It monitors the shapes along this axis as they advance through time. If the shapes cross on that axis, a collision is flagged. - Rotational Limitations: While this linear projection is highly efficient, extreme rotations within a single time step can occasionally cause glancing, purely rotational collisions to be missed. However, translational tunneling—the primary cause of game-breaking glitches—is entirely blocked.
The Sub-Stepping Solver and Motion Clamping
Once a valid collision path is identified, planck.js transitions the simulation into a specialized sub-stepping routine rather than relying entirely on its broad-phase and narrow-phase discrete solvers.
- Finding the First TOI: The engine evaluates pairs of potentially colliding objects and ranks them based on which pair will collide earliest in the current time step.
- Motion Clamping: The physics solver advances the global simulation time only up to that specific, fractional “Time of Impact” (\(t_{\text{impact}}\) where \(0 < t_{\text{impact}} \le \Delta t\)). The fast-moving object is physically “clamped” at its exact point of contact.
- Collision Resolution: At this precise sub-step, a localized contact manifold is generated, and the contact solver immediately processes the physical reaction (such as friction, restitution, or impulses).
- Advancing the Remainder: After resolving the event, the engine uses the remaining fraction of the time step (\(\Delta t - t_{\text{impact}}\)) to continue simulated movement for the rest of the world.
Implementing CCD in Code
By default, planck.js uses discrete collision detection to optimize performance, as continuous calculations are computationally heavy. To activate continuous collision detection for critical, high-velocity bodies (such as bullets or fast-moving characters), developers must explicitly flag the rigid body as a bullet.
// Create a fast-moving dynamic body
let bulletBody = world.createBody({
type: 'dynamic',
position: planck.Vec2(0, 0),
bullet: true // Enforces Continuous Collision Detection (CCD)
});Setting bullet: true instructs the system to run the TOI
sweep algorithms against all static geometry and other designated
dynamic obstacles, ensuring that high-velocity interactions remain
perfectly enclosed within the boundaries of the physics world.