What is Tunneling in Planck.js and How is it Fixed?
In game development, fast-moving physics objects can sometimes pass completely through solid barriers, a glitch known as tunneling. This article provides a quick overview of why tunneling occurs in 2D physics engines and explores how planck.js—a popular JavaScript rewrite of the Box2D engine—mitigates this issue. By implementing Continuous Collision Detection (CCD) and Time of Impact (TOI) calculations, planck.js ensures that high-speed projectiles and fast-moving characters collide accurately with boundaries rather than phasing through them.
Understanding the Tunneling Problem
To understand tunneling, it helps to look at how traditional physics engines update the game world. Most engines use Discrete Collision Detection, which checks for overlaps at fixed intervals or “ticks” of time.
If an object is moving at a normal speed, the engine catches the collision because the object overlaps with the barrier during one of those ticks. However, if an object is moving incredibly fast, it can be on one side of a wall during Tick A, and completely on the other side by Tick B. Because the engine never detects an explicit overlap during a tick check, the object effectively teleports through the wall.
How Planck.js Mitigates Tunneling
Planck.js prevents this frustrating phenomenon by utilizing Continuous Collision Detection (CCD). Instead of only looking at where objects are at specific moments in time, CCD looks at the entire sweeping path an object travels between ticks.
Planck.js handles this mitigation through several key mechanisms:
- Time of Impact (TOI) Calculations: When an object is flagged for CCD, planck.js calculates the exact fraction of time within the current frame step where a collision would first occur. It mathematically determines when the shapes will first touch along their trajectory.
- Sub-stepping: Once the TOI is found, the engine pauses the normal frame update for that object and advances it to the exact moment of impact. It then handles the collision response (like bouncing or stopping) before processing the remainder of the time step.
- The ‘Bullet’ Property: Because CCD requires more
CPU power, planck.js allows developers to selectively enable it. By
setting
body.setBullet(true)on a rigid body, you instruct the engine to use strict, continuous collision checks specifically for that fast-moving object, saving performance on slower entities.
By combining these methods, planck.js successfully keeps fast-moving game elements contained, maintaining physics accuracy even at extreme velocities.