Apply Continuous Force to Ammo.js Rigid Body
Applying a continuous directional force to an ammo.js rigid body
requires consistently invoking physics force methods within your
application’s simulation update loop. This article explains how to use
the applyCentralForce method, manage the rigid body’s
activation state to prevent the physics engine from putting it to sleep,
and implement a performance-friendly update loop for smooth, sustained
movement.
1. Choose the Right Force Method
Ammo.js provides two primary methods for applying forces to a
btRigidBody:
applyCentralForce(forceVector): Applies the force directly to the center of mass. This moves the body linearly without causing any rotation.applyForce(forceVector, relativePosition): Applies the force at a specific offset from the center of mass, which generates both linear force and torque (rotation).
For a standard directional push, applyCentralForce is
the most common choice.
2. Apply Force in the Update Loop
Because forces in physics engines are accumulated and cleared at the end of each physics step, applying a force once behaves like a temporary nudge (an impulse). To make the force continuous, you must apply it on every single frame inside your physics update loop.
Here is how to set up the vector and apply it continuously:
// 1. Create the force vector once (outside the loop to prevent memory leaks)
const forceDirection = new Ammo.btVector3(10.0, 0.0, 0.0); // Force acting along the X-axis
// 2. The main simulation loop
function updatePhysics(deltaTime) {
// Keep the rigid body active so the engine doesn't put it to "sleep"
rigidBody.activate(true);
// Apply the continuous force
rigidBody.applyCentralForce(forceDirection);
// Step the physics world
physicsWorld.stepSimulation(deltaTime, 10);
}3. Prevent the Rigid Body from Sleeping
Ammo.js automatically deactivates (puts to sleep) rigid bodies that have come to a rest or have very low velocity to optimize performance. Once a body is asleep, applying a force will not automatically wake it up.
To ensure your continuous force is always processed, you must call
activate(true) on the rigid body right before applying the
force, or change its activation state permanently during
initialization:
// Prevent the body from ever sleeping (use with caution for performance)
const DISABLE_DEACTIVATION = 4;
rigidBody.setActivationState(DISABLE_DEACTIVATION);4. Performance Optimization
Creating new btVector3 objects inside a high-frequency
update loop will rapidly trigger garbage collection, causing frame
drops. Always instantiate your force vectors once during setup and
update their values dynamically if the direction changes:
// Define once during setup
const continuousForce = new Ammo.btVector3(0, 0, 0);
// Update values dynamically when input changes
function updateForceVector(x, y, z) {
continuousForce.setValue(x, y, z);
}