Step 1 of 5 · Reading · ~4 min
Read
Production
Continuous Collision Detection (CCD)
Standard ("discrete") collision detection checks shapes for overlap at the start and end of each timestep — but never in between. That's fine for slow-moving objects, but fast-moving ones can pass straight through thin obstacles between two frames without the two shapes ever being detected as overlapping. This is the classic tunneling bug: a bullet, or any small object at high velocity, phases through a wall because at frame N it's on one side and at frame N+1 it's already on the other side, having "skipped over" the wall in between.
The fix: solve for time of impact, not just overlap
Continuous collision detection asks a different question than "do these shapes overlap right now?" It asks: given where a shape starts, where it's moving, and how far it moves this step, at what fraction of the step (a value t in [0, 1]) does it first touch the target? This is called the time of impact (TOI).
Once you know the TOI, you can either stop the object exactly at the surface (sub-stepping), or feed that time back into the constraint solver so the collision response happens at the right instant rather than after the object has already tunneled through.
The simplest case: circle vs. infinite plane
This lesson isolates the easiest non-trivial CCD case — a circle moving toward a horizontal plane — because the algebra is simple enough to derive by hand, and the reasoning generalizes to harder shape pairs later (circle vs. moving circle, polygon vs. polygon via conservative advancement).
A circle of radius r centered at (cx, cy) touches a plane at y = p exactly when the circle's edge reaches the plane — not when its center does. So the touching condition depends on which side you're approaching from:
- Approaching from above (
cy > p, moving down,vy < 0): the circle's bottom edge is atcy - r; it needs to reachp. Since we're solving for the center's position, that's equivalent to solvingcy + vy*t = p + r:t = (p + r - cy) / vy - Approaching from below (
cy < p, moving up,vy > 0): symmetric, usingp - r:t = (p - r - cy) / vy
Validating the result
A raw algebraic solution for t isn't automatically meaningful — you have to check it actually corresponds to a collision within this step:
- If
t < 0, the hit (mathematically) happened in the past — not relevant to this step. - If
t > 1, the hit would happen, but not until after this step's motion completes — no hit this step; the discrete check on the next step will catch it fine since nothing has been skipped over. - If the body isn't actually moving toward the plane at all (e.g., above the plane but moving further up), there's no valid
t— report no hit rather than returning a nonsensical value.
There's also a degenerate starting condition to check first, before doing any of the above algebra: if the circle is already overlapping the plane at the start of the step (|cy - p| <= r), the time of impact is trivially t = 0 — it already happened.
The next case up: two moving circles
Circle-vs-plane has a linear solution because the plane does not move. Once both shapes move, work in the RELATIVE frame: let d = c_a - c_b be the starting separation and v = v_a - v_b the relative velocity. The circles touch when |d + v*t| = r_a + r_b; square both sides and you get a quadratic in t:
(v . v) t^2 + 2 (d . v) t + (d . d - (r_a + r_b)^2) = 0
Real roots exist only when the discriminant is non-negative; take the SMALLER root, since that is the first touch, and keep it only if it lands in [0, 1]. Notice the shape of the answer is the same as the plane case - solve for the instant of contact, then validate the interval - only the algebra changed from a division to a quadratic.
Why this matters for the engine as a whole
In a full engine, CCD is usually reserved for fast-moving or small objects (bullets, thin projectiles) because it's more expensive than discrete checks — you'd run a discrete broad-phase pass for most bodies and only fall back to a CCD solve for objects whose per-frame displacement exceeds some fraction of their own size (a common heuristic: displacement > half the object's smallest dimension). Once you have TOI for one shape pair, the "conservative advancement" technique that generalizes this to arbitrary convex shapes builds directly on the same idea: bound how fast the separation between two shapes can change, and use that bound to safely step forward in time without ever tunneling.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…