Skip to main content

Getting Started

PlayCanvas physics is powered by ammo.js, a port of the open source Bullet physics engine to WebAssembly. Once it is loaded, you build a simulation out of entities that carry a rigidbody component, which decides how the entity moves, and a collision component, which gives it a shape. This page covers loading the library, the global settings, and the rules that every other page in this section builds on.

Enabling Physics

Physics is opt-in. ammo.js weighs in at several hundred kilobytes, so nothing loads it unless you ask. It is distributed as three files: the WebAssembly module ammo.wasm.wasm, its JavaScript glue ammo.wasm.js, and ammo.js, an asm.js fallback for browsers without WebAssembly support. Until the library is present, physics components are inert placeholders: adding them does nothing and raises no errors.

Load the module before creating the application. The three files ship with the engine repository under examples/assets/wasm/ammo/ and in the sync-ammo npm package.

pc.WasmModule.setConfig('Ammo', {
glueUrl: 'ammo/ammo.wasm.js',
wasmUrl: 'ammo/ammo.wasm.wasm',
fallbackUrl: 'ammo/ammo.js'
});

// Wait for the module, then create the application as usual
await new Promise((resolve) => {
pc.WasmModule.getInstance('Ammo', () => resolve());
});

const app = new pc.Application(canvas);

The rigid body system finds the Ammo global as the application starts and installs the ammo.js backend. pc.Application registers every component system for you; if you build from pc.AppBase and pc.AppOptions instead, add pc.CollisionComponentSystem and pc.RigidBodyComponentSystem (and pc.JointComponentSystem for joints) to componentSystems. The Falling Shapes example shows the complete sequence.

Gravity

Gravity is a constant acceleration applied to every dynamic rigid body. The default of -9.81 along the world's Y axis (straight down) approximates Earth. Set it to zero for a game in space, or to something smaller for the Moon.

// Lunar gravity. The older setGravity() method is deprecated in favor of this property.
app.systems.rigidbody.gravity = new pc.Vec3(0, -1.62, 0);

Units of Measurement

The physics engine interprets 1 unit as 1 meter and measures mass in kilograms. For objects to fall at a rate that looks right, size your scenes accordingly: a character who is 1.8 m tall should be 1.8 units high. Scenes built at a very different scale still simulate, but gravity will look too weak or too strong, and very small shapes are prone to tunneling through one another.

How the Simulation Runs

A few rules follow from the way the engine drives the simulation, and the rest of this section relies on them:

  • The simulation steps at a fixed rate. Each frame, the physics world advances in fixed steps of 1/60 of a second, taking as many as the frame time requires (up to a limit). Bodies therefore behave the same at 30 and at 144 frames per second. On displays faster than 60 Hz some frames run no step at all, and body transforms are interpolated so that motion stays smooth.
  • Physics owns dynamic bodies. After each step the engine writes the position and rotation of every dynamic body back to its entity. Anything you set on the entity's transform is overwritten, so dynamic bodies are moved with forces, velocities or teleport instead (see Rigid Bodies).
  • You own static and kinematic bodies. Their transforms are read from the entity at the start of each step, so you move them like any other entity.
  • Events fire per step. Collision and trigger events are reported once per physics step, not per frame. A body resting on the floor produces a contact event every step for as long as it rests there.

See Also