Havok Physics in Babylon.js
The Havok integration in Babylon.js consists of two layers. The Havok engine itself is a WASM binary that handles all physics calculations. The Babylon.js HavokPlugin bridges the engine to the scene, automatically synchronizing mesh transforms with physics body states each frame. This means that unlike standalone engines such as Rapier or Cannon-es, you do not write a manual sync loop. Babylon.js handles it for you.
Load the Havok WASM Module and Initialize the Plugin
Install the Havok package: npm install @babylonjs/havok. Import it at the top of your entry file: import HavokPhysics from '@babylonjs/havok'. The HavokPhysics function is async because it loads and compiles the WASM binary. Await it during your loading phase: const havokInstance = await HavokPhysics(). This returns a handle to the compiled engine.
Next, create the plugin: const havokPlugin = new BABYLON.HavokPlugin(true, havokInstance). The first argument enables debug rendering (set to false in production). Pass this plugin when enabling physics on your scene. If you are loading Babylon.js from the CDN instead of npm, the Havok WASM file is available at cdn.babylonjs.com/havok/HavokPhysics_umd.js. Load it with a script tag and call the global HavokPhysics() function.
Havok requires WebAssembly SIMD support in the browser. All modern desktop browsers (Chrome, Firefox, Edge, Safari 16.4 and later) support this. On iOS, devices running iOS 16.4 or later have full support. Older iOS versions will fail to initialize the WASM module. If you need to support older mobile devices, consider falling back to Cannon-es or Ammo.js, though for most game audiences in 2026 this is not a concern.
Enable Physics on the Scene
With the plugin ready, enable physics: scene.enablePhysics(new BABYLON.Vector3(0, -9.81, 0), havokPlugin). The first argument is the gravity vector. Standard Earth gravity points downward on the y-axis at -9.81 meters per second squared. For a low-gravity moon environment, use -1.62. For zero gravity, pass Vector3.Zero().
Once enabled, the scene's render loop automatically steps the physics world. You do not need to call a step function manually. Babylon.js calls the Havok step internally before each render, and it handles the fixed-timestep accumulator pattern for you. Body positions are interpolated between physics steps for smooth rendering. This automation is one of the main advantages of using Havok through Babylon.js rather than as a standalone engine.
Create Physics Bodies and Shapes
In Babylon.js with Havok, physics bodies are attached to meshes. Create your visual mesh normally (a box, sphere, imported glTF model, or any Mesh), then wrap it with a PhysicsBody: const body = new BABYLON.PhysicsBody(mesh, BABYLON.PhysicsMotionType.DYNAMIC, false, scene). The motion type can be DYNAMIC (fully simulated), STATIC (immovable), or ANIMATED (kinematic, moved by code).
The third parameter controls whether the body starts as a sensor (trigger volume that detects overlaps without producing collision response). Set it to false for normal solid bodies and true for trigger zones like pickup areas or damage fields.
Attach a collision shape: const shape = new BABYLON.PhysicsShapeBox(new BABYLON.Vector3(0, 0, 0), BABYLON.Quaternion.Identity(), new BABYLON.Vector3(2, 2, 2), scene). The parameters are center offset, rotation, and full size (not half-extents like some engines). Assign it: body.shape = shape. Havok supports PhysicsShapeBox, PhysicsShapeSphere, PhysicsShapeCapsule, PhysicsShapeCylinder, PhysicsShapeConvexHull, PhysicsShapeMesh (for static geometry), and PhysicsShapeContainer (compound shape holding multiple child shapes).
For imported glTF models, you can generate a convex hull shape automatically from the mesh vertices, or use a simplified bounding box or capsule for better performance. Complex characters should use a capsule shape for the physics body even if their visual mesh has thousands of polygons.
Set mass directly: body.setMassProperties({ mass: 10 }). Or let Havok compute mass from the shape volume and a density value on the shape. Heavier objects are harder to push and require more force to accelerate, which creates natural-feeling interactions where a bowling ball behaves differently from a beach ball.
Configure Material Properties
Physical material properties in Havok are set on the shape, not on a separate material object. Set friction with shape.material = { friction: 0.5, restitution: 0.3 }. Alternatively, set them individually: shape.material.friction = 0.5 and shape.material.restitution = 0.3.
Friction determines how much surfaces grip. A value of 0 means perfectly slippery (ice), while 1.0 is very grippy (rubber on asphalt). Restitution determines bounciness. A value of 0 means no bounce at all, while 1.0 means a perfectly elastic collision where no kinetic energy is lost. Most game objects work well with friction between 0.3 and 0.6 and restitution between 0.0 and 0.3.
When two shapes with different material properties collide, Havok combines them using a formula that averages friction and takes the maximum restitution. This means one very bouncy object hitting a non-bouncy surface still produces some bounce, which matches physical intuition.
Add Constraints Between Bodies
Constraints connect two bodies and limit their relative movement. Babylon.js exposes Havok constraints through dedicated classes. BallAndSocketConstraint creates a joint that rotates freely in all directions, like a shoulder. HingeConstraint allows rotation around a single axis, like an elbow or door hinge. SliderConstraint allows linear motion along one axis, like a piston. LockConstraint removes all relative motion, welding two bodies together. SpringConstraint applies a spring force between two points.
To build a hinge door: const hinge = new BABYLON.HingeConstraint(pivotA, pivotB, axisA, axisB, scene). Attach it to the two bodies: body1.addConstraint(body2, hinge). The pivots define the connection point relative to each body's center, and the axes define the rotation axis in each body's local space. You can set angular limits on the hinge to prevent the door from swinging past 90 degrees, or add a motor that applies torque to open and close automatically.
For ragdolls, build a chain of bodies connected by ball-and-socket and hinge constraints with angular limits. The torso connects to upper arms via ball-and-socket joints with cone limits. Upper arms connect to lower arms via hinge joints with 0 to 140 degree limits. The head connects to the torso via a ball-and-socket with tight limits. The ragdolls and joints guide covers this in full detail.
Use Raycasting and Collision Observables
Raycasting in Havok through Babylon.js uses the PhysicsEngine's raycast method: const result = scene.getPhysicsEngine().raycast(origin, destination). The result includes hasHit, hitPoint, hitNormal, and the body that was struck. Use this for ground detection (cast from the player's center downward), line-of-sight (cast from the camera to a target), and mouse picking (cast from the camera through the pointer position using scene.createPickingRay).
Collision events are handled through observables on the physics body. Subscribe with body.getCollisionObservable().add((event) => { ... }). The event provides the colliding body, the contact point, the contact normal, and the impulse magnitude. Use this for impact damage, sound effect triggering, and score systems. For trigger zones (sensors), create a body with the sensor flag set to true and listen to its collision observable to detect when players enter or leave the zone.
You can also filter collisions by assigning bodies to collision groups using body.shape.filterMembership and body.shape.filterCollideMask. This is a bitmask system where each bit represents a group. A body only collides with another if the first body's membership intersects the second body's collide mask and vice versa. Use this to prevent friendly fire, let ghosts pass through walls, or separate physics layers for different game systems.
Havok inside Babylon.js gives you AAA-quality physics with automatic transform synchronization, no manual step loop, and the best raw performance of any web physics option. The trade-off is that it only works well inside Babylon.js. If you are already using Babylon.js for rendering, Havok is the clear choice for physics.