Why Small Ammo.js Collision Shapes Behave Erratically

When working with small 3D physics bodies in ammo.js, developers often encounter erratic behaviors like jittering, clipping through surfaces, or bouncing unpredictably. This article explains how the underlying Bullet Physics engine handles collision detection for small shapes and why adjusting the collision margin is essential to restoring stability and accuracy to your simulations.

The Role of the Collision Margin

Ammo.js (a direct port of the Bullet Physics engine) utilizes a concept called “collision margin” to optimize collision detection and improve performance. By default, the engine adds an invisible protective shell—typically 0.04 units wide—around collision shapes.

For standard-sized objects (such as a box of 1x1x1 meters), a 0.04-meter margin is negligible and helps the collision detection algorithms (like GJK and EPA) identify contact points quickly before the actual geometries intersect.

Why Small Shapes Break with Default Margins

When a collision shape is very small, the default collision margin becomes highly problematic due to scale conflict and solver overcompensation.

1. Shape Distortion and Scale Conflict

If you create a sphere with a radius of 0.05 units, a default margin of 0.04 units means that 80% of the object’s radius is comprised of the collision margin. For some shapes, like cones or cylinders, the margin can completely swallow the actual geometry, rounded out corners aggressively, or cause the shape to behave as if it is much larger and rounder than it actually is.

2. Deep Penetration and Explosive Solver Forces

The physics solver relies on the margin to detect early, shallow contacts. If an object is smaller than or close to the size of the margin, a single simulation step can cause the object to completely bypass this protective boundary.

When an object penetrates deep into another body past the margin, the engine’s constraint solver detects a massive overlap. To resolve this, it applies a violent corrective force in the next frame. This results in the object “exploding” away, jittering constantly on flat surfaces, or clipping entirely through solid ground.

How to Fix Small Collision Shape Behavior

To resolve erratic physics behavior for small objects in ammo.js, you must tune the margins and simulation parameters.

Adjust the Shape Margin Explicitly

You can manually shrink the collision margin for small objects. For convex shapes, use the setMargin method to lower the boundary to a size proportional to the object.

// Example: Setting a smaller margin for a tiny box
var colShape = new Ammo.btBoxShape(new Ammo.btVector3(0.05, 0.05, 0.05));
colShape.setMargin(0.005); // Reduce margin to 5 millimeters

Note that setting the margin to absolute zero is generally not recommended, as it can disable certain collision detection optimizations and cause objects to fall through one another. Keep a tiny, proportional margin.

Scale Up Your Physics World

Bullet Physics is optimized for real-world meters, kilograms, and seconds, operating best with objects sized between 0.2 and 5.0 units. If your game or simulation requires many small objects (like marbles or small debris), the most robust solution is to scale up your physics world. Treat 10 units in ammo.js as 1 meter in your visual renderer, and scale gravity and forces accordingly.

Increase Simulation Substeps

If you must keep objects small, you can prevent them from bypassing collision margins by increasing the physics step frequency. By allowing the physics simulation to step more frequently, you ensure that fast-moving, small objects are checked for collisions before they can deeply penetrate other surfaces.

// Increase maxSubSteps (second parameter) and decrease fixedTimeStep (third parameter)
physicsWorld.stepSimulation(deltaTime, 10, 1 / 120);