Optimize Ammo.js Performance with Physics Sleeping
Ammo.js, the WebAssembly port of the Bullet physics engine, can quickly become a performance bottleneck in complex 3D web applications. This article provides a guide on how to utilize physics sleeping states—also known as rigid body deactivation—to heavily optimize your ammo.js simulation, ensuring high frame rates by bypassing physics calculations for idle objects.
Understanding Physics Sleeping in Ammo.js
In a typical 3D scene, many physics objects eventually come to rest. Calculating collisions, gravity, and velocity for hundreds of stationary objects on every frame wastes massive amounts of CPU power.
To solve this, Ammo.js employs a feature called “sleeping” (or deactivation). When a rigid body’s linear and angular velocities fall below a certain threshold for a specified amount of time, the physics engine puts the body to sleep. While asleep, the engine excludes the object from active dynamics simulation and collision detection passes, drastically reducing CPU overhead. The object remains dormant until another active physical body collides with it or a force is manually applied, at which point it “wakes up” automatically.
How to Configure and Fine-Tune Sleeping States
To maximize performance, you must properly configure how and when your rigid bodies fall asleep.
1. Enable Sleeping Globally
First, ensure that your physics world allows sleeping. When instantiating your collision dispatcher, sleeping is usually enabled by default, but you should confirm your configuration:
const collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
const dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
// Sleeping is managed automatically by the dynamics world
const dynamicsWorld = new Ammo.btDiscreteDynamicsWorld(
dispatcher,
overlappingPairCache,
solver,
collisionConfiguration
);2. Set Custom Sleeping Thresholds
By default, Ammo.js uses predefined thresholds to determine when an
object is “idle.” You can fine-tune these thresholds on a per-body basis
to make objects sleep sooner. Use
setSleepingThresholds(linear, angular) to define the
velocity limits below which an object is considered ready to sleep:
// Lower thresholds keep objects active longer; higher thresholds make them sleep sooner
const linearThreshold = 0.8; // Linear velocity threshold
const angularThreshold = 1.0; // Angular velocity threshold
rigidBody.setSleepingThresholds(linearThreshold, angularThreshold);3. Adjust Deactivation Time
An object must remain below the velocity thresholds for a specific
duration before it transitions to a sleeping state. You can set this
duration using setDeactivationTime:
// The object must be almost still for 1.5 seconds before sleeping
rigidBody.setDeactivationTime(1.5);Managing Activation States Manually
Ammo.js represents the state of a rigid body using integer activation states. Understanding these states allows you to force optimization on specific objects:
1 (ACTIVE_TAG): The body is active and simulating.2 (ISLAND_SLEEPING): The body is currently sleeping and optimized.3 (WANTS_DEACTIVATION): The body is transitioning to sleep.4 (DISABLE_DEACTIVATION): The body will never sleep. Avoid this state for non-essential objects, as it forces Ammo.js to calculate physics for the object indefinitely.5 (DISABLE_SIMULATION): The body is completely ignored by the simulation.
If you instantiate objects that you know will start in a resting position (such as debris, bricks, or dropped loot), force them to sleep immediately upon creation to save initial CPU cycles:
// Force the body to sleep immediately after adding it to the world
rigidBody.forceActivationState(2); // ISLAND_SLEEPINGConversely, if you manually move an object via code (outside of the physics engine) and need it to interact with the environment again, you must wake it up:
rigidBody.activate();Common Pitfalls to Avoid
To ensure sleeping states optimize your performance without breaking gameplay mechanics, keep the following practices in mind:
- Avoid constantly modifying positions manually: Directly updating a rigid body’s transform via its motion state or world transform every frame prevents it from ever entering a sleeping state.
- Do not use DISABLE_DEACTIVATION indiscriminately: Only disable deactivation for critical objects like player characters or fast-moving projectiles that must remain highly responsive.
- Watch out for floating-point jitter: If your physics collision shapes are imperfectly aligned, objects might micro-collide and jitter indefinitely, preventing them from falling below the sleeping thresholds. Ensure proper collision margins and physical spacing.