Physics in Babylon.js with the Havok Engine
Physics simulation makes game worlds feel real. Objects fall under gravity, bounce off surfaces, stack on top of each other, and respond to forces. Without physics, a game relies entirely on hand-coded movement rules that become brittle as complexity grows. With Havok running in the browser, Babylon.js games can have physically accurate environments where crates tumble, doors swing, characters stand on moving platforms, and ragdoll bodies collapse realistically.
Step 1: Initialize the Havok Plugin
Install the Havok package with npm install @babylonjs/havok. Import the initialization function and call it to load the WebAssembly module: const havokInstance = await HavokPhysics(). This is an async operation because the WASM binary needs to be downloaded and compiled by the browser. Once initialized, create the plugin and enable it on the scene:
const havokPlugin = new BABYLON.HavokPlugin(true, havokInstance) followed by scene.enablePhysics(new BABYLON.Vector3(0, -9.81, 0), havokPlugin). The gravity vector points downward at 9.81 meters per second squared, matching Earth's gravity. You can adjust this for different game feels: lower gravity for a moon environment, zero gravity for space, or exaggerated gravity for fast-paced arcade action.
The first parameter to HavokPlugin controls whether the simulation runs in deterministic mode. Deterministic mode guarantees identical results across runs with the same inputs, which is important for replays and networked games where all clients must simulate identically. Non-deterministic mode may be slightly faster but can produce different results on different hardware.
Step 2: Create Physics Bodies and Shapes
A physics body is the simulation representation of a mesh. Create one with new BABYLON.PhysicsBody(mesh, BABYLON.PhysicsMotionType.DYNAMIC, false, scene). The motion type determines behavior: DYNAMIC bodies move freely under forces and gravity, STATIC bodies never move (walls, floors, terrain), and KINEMATIC bodies move only through code (moving platforms, elevators) and push dynamic bodies out of the way.
Every body needs a collision shape. The simplest shapes are primitives: new BABYLON.PhysicsShapeBox(center, rotation, extents, scene) for boxes, new BABYLON.PhysicsShapeSphere(center, radius, scene) for spheres, and new BABYLON.PhysicsShapeCapsule(pointA, pointB, radius, scene) for capsules. Capsules are the standard choice for character colliders because they slide smoothly along walls and over small obstacles.
For complex geometry, use PhysicsShapeConvexHull which creates a convex wrapping of the mesh vertices, or PhysicsShapeMesh which uses the exact triangle mesh for collision. Convex hulls are faster and suitable for most objects. Mesh shapes are accurate but expensive, and should only be used for static geometry like terrain or level architecture where the exact surface matters for gameplay.
Set physical properties on the shape: shape.material = { friction: 0.5, restitution: 0.3 }. Friction controls how much surfaces resist sliding (0 is ice, 1 is rubber). Restitution controls bounciness (0 absorbs all energy, 1 is a perfect bounce). Mass is set on the body with body.setMassProperties({ mass: 10 }). Heavier objects are harder to push and fall at the same rate as light objects (physics is correct about this).
Step 3: Set Up a Character Controller
The Havok character controller is a specialized body designed for player movement. Unlike raw dynamic bodies, it handles ground detection, slope limits, step heights, and prevents the character from being pushed by lightweight objects. Create it by attaching a capsule shape to a kinematic body and using the character controller API to manage movement.
Ground detection tells the controller whether the character is standing on a surface. This determines whether the character can jump, how fast it should move (air movement is typically slower than ground movement), and whether gravity should be applied. The controller's isGrounded state updates automatically based on a downward ray cast from the capsule's bottom.
Slope handling prevents the character from walking up surfaces that are too steep. Set a maximum slope angle (typically 45 to 60 degrees), and the controller will treat steeper surfaces as walls rather than walkable ground. The character slides down slopes steeper than the limit, which feels natural and prevents players from climbing vertical walls.
Step handling allows the character to walk up small ledges without jumping. Set a maximum step height (typically 0.3 to 0.5 meters), and the controller automatically lifts the character over obstacles shorter than that threshold. Without step handling, the character would stop dead when hitting a curb or a stair riser, which feels broken to players.
Step 4: Add Constraints and Joints
Constraints connect two physics bodies with a mechanical joint. The HingeConstraint creates a door-like pivot around a single axis. Specify the pivot point and the hinge axis on each body. A door hinge uses a vertical axis at the door's edge. Add angular limits to prevent the door from swinging more than 90 degrees, or leave it unlimited for a freely spinning wheel.
The BallAndSocketConstraint allows rotation around all three axes from a fixed point, like a shoulder joint or a hanging lantern. The PrismaticConstraint restricts movement to a single axis, like a sliding drawer or a piston. The LockConstraint fixes two bodies together rigidly, which is useful for compound objects made of multiple physics bodies that should move as one.
Motors power constraints for mechanical movement. A hinge motor can rotate a door to a target angle with a specific torque, simulating a self-closing hinge or a rotating turret. A prismatic motor can drive an elevator platform between two positions. Motors have max force and target velocity parameters that control how aggressively they reach their target.
For vehicles, combine prismatic constraints (suspension), hinge constraints (wheel axles), and motors (engine torque). The suspension constrains each wheel to move vertically relative to the chassis with spring-like behavior. The wheel axle constrains rotation to a single axis. The engine motor applies torque to the drive wheels. This constraint-based approach produces realistic vehicle physics without custom vehicle code.
Step 5: Build Ragdoll Physics
Ragdoll physics replaces animated character motion with physically simulated bodies when a character dies or gets hit with a large force. The skeleton's bones become physics bodies connected by joint constraints that limit their range of motion. When activated, the ragdoll collapses under gravity and reacts to impact forces, producing unique, unscripted death and knockback animations.
Build a ragdoll by creating a physics body for each major bone: hips, spine, chest, head, upper arms, lower arms, upper legs, and lower legs. Attach each body to its corresponding bone with a transform that matches the bone's position and orientation. Connect adjacent bodies with ball-and-socket constraints that have angular limits matching human joint ranges: the elbow bends 0 to 150 degrees, the knee bends 0 to 140 degrees, the neck rotates about 45 degrees in each direction.
The transition from animation to ragdoll needs to be seamless. Before activating the ragdoll, read the current bone positions and velocities from the animation system and apply them to the physics bodies. This way, the ragdoll starts from the character's current pose with the correct momentum, rather than snapping to a T-pose. Disable the animation system for the skeleton and let physics take over completely.
After the ragdoll settles, you can optionally blend back to animation. Read the final ragdoll pose, create a transition animation that interpolates from the ragdoll pose to a "getting up" animation, then switch back to the animation system. This creates a satisfying recovery sequence where the character picks itself up from whatever position it landed in.
Step 6: Optimize Physics Performance
The physics simulation runs at a fixed time step, defaulting to 60 updates per second. If the rendering frame rate drops below the simulation rate, the physics engine runs multiple simulation steps per frame to catch up, which makes the problem worse. Reduce the simulation rate to 30 Hz for games that do not need high-fidelity physics, or use the maxSteps parameter to limit catch-up steps per frame.
Use simple collision shapes wherever possible. A box shape is dramatically faster than a mesh shape. For a complex building model, use a collection of box shapes that approximate the walls, floors, and pillars rather than a single mesh shape that traces every polygon. The visual mesh can be as detailed as you want; the physics shape only needs to approximate the surfaces that gameplay interacts with.
Sleep states save performance for objects at rest. When a physics body has been stationary for a few frames, the engine puts it to sleep, excluding it from the simulation entirely. It wakes up automatically when another body contacts it or when a force is applied. In a scene with 500 crates stacked on the floor, only the few crates involved in an active collision are being simulated; the rest are sleeping at zero cost.
Collision filtering prevents unnecessary collision checks between objects that should never interact. Use collision groups and masks to specify which categories of bodies can collide with each other. Player bullets should collide with enemies and environment but not with other bullets. Terrain debris should collide with the ground but not with the player. Proper filtering reduces the number of collision pairs the engine evaluates, which is one of the most effective physics optimizations.
Havok in Babylon.js provides console-quality physics in the browser. Use simple shapes for performance, the character controller for player movement, constraints for mechanical objects, and ragdolls for impactful character physics. The key optimization is using the simplest collision shapes that produce acceptable gameplay.