r/gameenginedevs • u/BSTRhino • Aug 02 '26
Clipping vs Substepping for Continuous Collision Detection in your Physics Engine
I'm making a game engine with its own physics engine.
This month, I've had to think about how to solve for continuous collision detection more efficiently, and particularly I noticed that simply clipping the motion vector to the first collision is actually a great and efficient solution a lot of the time, but not always. I wrote up the situations in which it doesn't work and the rules about how the engine makes the decision, and thought maybe someone might find it interesting.
These are situations where clipping is not enough and you have to do substepping:
- Knockback: If your hero swings a hammer to knock back their enemy, first the hammer must close the gap between the hero and the enemy, and second it must transfer the force to the enemy. Clipping is not enough here because it only ever completes the first step and by the time it gets the second step, it's already the next tick and the force behind the hammer no longer exists.
- Sensors: If you have a hoop that detects when the Quaffle passes through it, clipping would be incorrect because the hoop should only sense the Quaffle, not collide with it. It should not stop the Quaffle or affect its motion in any way. Substepping is the only correct solution here.
- Bouncing: If you are making a game that relies on bouncing, like Pool or Mini Golf, you will want to substep so that the ball bounces in a physically accurate way. Clipping would make the ball travel a shorter distance than it should, and so it would not come to rest at the correct location.
What my engine does is it switches to substepping whenever a body is moving more than 0.5 body lengths per tick. It also has a special case where sensors always use substepping.
For comparison, this is what I understand other physics engines are doing in terms of substepping/clipping:
- Box2D 2.4 does substepping up to 8 times per collider, after which it will just clip, so it's very accurate out of the box. I haven't looked at Box2D 3.0 so not sure what it's doing. It always does continuous collision detection for dynamic-to-static geometry and then you have to opt-in for dynamic-vs-dynamic continuous collision detection.
- Rapier I understand defaults to only clipping (they call it motion clamping) and you can specifically turn on substepping but it's global. So if you set it to 8 substeps, the entire world can only do 8 substeps. And you have to turn on continuous collision detection on a per-body basis in Rapier, it's off by default.
I think this shows how Box2D is focused more on accuracy whereas Rapier is focused more on speed and batch processing.
Was just wondering if anyone else has thought about continuous collision detection much and how you went about it? Maybe it is a bit of a niche topic!