Using A Physics Engine
Introduction
Babylon.js has a plugin system for physics engines that enables users to add physics interactions to scene objects. Unlike the internal collision system, a physics engine calculates objects' body dynamics and emulates "real-life" interactions between them. So if two objects collide, they will "bounce" off one another, just like you would expect from a real-life object.
The plugin system allows us to use well-established physics engines and integrate them into the render loop. Apart from very advanced usage, there is no need to interact directly with the physics engine. Babylon.js does the work for you.
Which physics engine is integrated
There is a plugin for the Havok Physics engine.
Read about the Babylon.js Havok plugin and how to use it directly.
Basic usage
Enabling the physics engine
To enable the physics engine, call the scene's enablePhysics function:
import { Vector3 } from "@babylonjs/core/Maths/math.vector";import { HavokPlugin } from "@babylonjs/core/Physics/v2/Plugins/havokPlugin";import { Scene } from "@babylonjs/core/scene";var scene = new Scene(engine);var gravityVector = new Vector3(0, -9.81, 0);var physicsPlugin = new HavokPlugin();scene.enablePhysics(gravityVector, physicsPlugin);Both parameters are optional. The default parameters are shown in the example. This is the same as calling:
scene.enablePhysics();import { Vector3 } from "@babylonjs/core/Maths/math.vector";import { HavokPlugin } from "@babylonjs/core/Physics/v2/Plugins/havokPlugin";scene.enablePhysics(new Vector3(0, -9.81, 0), new HavokPlugin());Calling this function will create a new PhysicsEngine object that handles the physics interactions.
The physics engine is now enabled and is running during the render loop.
Your first physics scene
Here we present a minimal example of a physics-enabled scene, using Aggregates for faster creation:
import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera";import { HemisphericLight } from "@babylonjs/core/Lights/hemisphericLight";import { Vector3 } from "@babylonjs/core/Maths/math.vector";import { MeshBuilder } from "@babylonjs/core/Meshes/meshBuilder";import { PhysicsShapeType } from "@babylonjs/core/Physics/v2/IPhysicsEnginePlugin";import { PhysicsAggregate } from "@babylonjs/core/Physics/v2/physicsAggregate";import { HavokPlugin } from "@babylonjs/core/Physics/v2/Plugins/havokPlugin";import { Scene } from "@babylonjs/core/scene";var createScene = function () { // This creates a basic Babylon Scene object (non-mesh) var scene = new Scene(engine); // This creates and positions a free camera (non-mesh) var camera = new FreeCamera("camera1", new Vector3(0, 5, -10), scene); // This targets the camera to scene origin camera.setTarget(Vector3.Zero()); // This attaches the camera to the canvas camera.attachControl(canvas, true); // This creates a light, aiming 0,1,0 - to the sky (non-mesh) var light = new HemisphericLight("light", new Vector3(0, 1, 0), scene); // Default intensity is 1. Let's dim the light a small amount light.intensity = 0.7; // Our built-in 'sphere' shape. var sphere = MeshBuilder.CreateSphere("sphere", { diameter: 2, segments: 32 }, scene); // Move the sphere upward at 4 units sphere.position.y = 4; // Our built-in 'ground' shape. var ground = MeshBuilder.CreateGround("ground", { width: 10, height: 10 }, scene); // initialize plugin var hk = new HavokPlugin(); // enable physics in the scene with a gravity scene.enablePhysics(new Vector3(0, -9.8, 0), hk); // Create a sphere shape and the associated body. Size will be determined automatically. var sphereAggregate = new PhysicsAggregate(sphere, PhysicsShapeType.SPHERE, { mass: 1, restitution: 0.75 }, scene); // Create a static box shape. var groundAggregate = new PhysicsAggregate(ground, PhysicsShapeType.BOX, { mass: 0 }, scene); return scene;};Physicalize GLTF
An extra step is needed to physicalize meshes imported from glTF in a left-handed scene. Insert an extra transform node just before the __root__ so the loader's right-to-left-handed conversion is transparent to the physics engine. See Coordinate Systems and Handedness for an explanation of the imported root.
import { TransformNode } from "@babylonjs/core/Meshes/transformNode";const trParent = new TransformNode("tr", scene);const root = scene.getMeshByName("__root__");root.setParent(trParent);Debugging your scene
Use the physics debug display when your scene and dynamics don't behave the way you think they should. It will display geometry the way the physics engine sees the world. There are two ways to invoke the display.
Programmatically
import { PhysicsViewer } from "@babylonjs/core/Debug/physicsViewer";physicsViewer = new PhysicsViewer();for (const mesh of scene.rootNodes) { if (mesh.physicsBody) { const debugMesh = physicsViewer.showBody(mesh.physicsBody); }}This snippet creates the PhysicsViewer and then adds every PhysicsBody available from the scene's meshes.
Using the Inspector
You can turn on and off the Physics Viewer on the Debug Tab of the Inspector:
