Why Modifying Ammo.js Objects in Collision Loops is Dangerous

Modifying ammo.js objects, such as rigid bodies or collision shapes, directly inside a collision detection iteration loop can lead to critical memory corruption, application crashes, and unpredictable physics behavior. This article explains the underlying mechanics of why these direct modifications are dangerous in the WebAssembly/Emscripten-compiled environment of ammo.js and provides the safest methods for handling collision-triggered changes.

The Problem with WebAssembly and C++ Memory

Ammo.js is a direct port of the Bullet Physics engine written in C++. It runs in JavaScript via Emscripten and WebAssembly (Wasm). Unlike native JavaScript objects, which are managed by a garbage collector, ammo.js objects reside in a restricted, manually-managed WebAssembly memory heap.

When you query collisions in ammo.js, you typically iterate through the dispatcher’s contact manifolds. During this iteration, the physics engine holds direct pointers to the active rigid bodies and collision structures involved in those contacts.

Iterator Invalidation and Memory Corruption

If you destroy, remove, or significantly alter an ammo.js object (such as changing its mass, collision flags, or removing it from the dynamics world) while inside this iteration loop, you cause several immediate issues:

The Safe Solution: Deferred Execution

To safely modify physics objects based on collision events, you must defer any state changes or deletions until after the physics simulation step has completely finished.

  1. Queue the Changes: During the collision loop, do not modify the ammo.js objects. Instead, record the target objects and the intended actions (e.g., deletion, force application, or layer changes) into a standard JavaScript array or queue.
  2. Process Post-Step: Once the dynamicsWorld.stepSimulation() function has fully resolved and the collision loop has exited, iterate through your custom queue.
  3. Apply the Modifications safely: Perform the removals, modifications, or deletions on the queued objects outside of the physics engine’s internal solver loop.