RigidBody
The RigidBody component turns an object into a fully simulated dynamic body - it falls under gravity, responds to forces, and bounces off other colliders.
What RigidBody does
Add a RigidBody and, during Play, the object becomes a dynamic physics body: Rapier integrates its motion every step and Awaken writes the result back into the object's Transform. Without a RigidBody, a Collider alone is static scenery - solid and immovable. The RigidBody is what says "this thing moves."
A RigidBody on its own has no shape and is never added to the simulation. It needs a Collider on the same object (a Collider with an empty shape list falls back to one default box so Play still works, but give it a real shape).
The component fields
RigidBody has seven fields, edited in the Inspector:
| Field | Type | Default | Meaning |
|---|---|---|---|
velocity | vec3 | (0, 0, 0) | Starting linear velocity in world units/second, read once when the body is built: at Play, or the moment the object is spawned. It is not a live readout, and writing it during Play does nothing. |
useGravity | bool | true | On: the body falls under gravity (0, -9.81, 0). Off: its gravity scale is 0, so it keeps its velocity and still collides but never falls. |
restitution | number | 0.3 | Bounciness, 0–1. Becomes the restitution of every collider shape on this object - 0 = no bounce, 1 = fully elastic. Rapier combines it with what it hits. |
mass | number | 0 | Mass in kg. 0 = from the colliders' volume at 1 kg per cubic unit, so a 1 x 1 x 1 box weighs 1 kg. Set it when the body must push and be pushed with a real weight: a 1200 kg car shoves a 25 kg crate aside. Rotational inertia scales with it. |
centerOfMass | vec3 | (0, 0, 0) | Moves the centre of mass from the colliders' own centre, in local units. (0, -0.3, 0) lowers it 0.3, so the body is harder to tip over. |
linearDamping | number | 0 | How fast the body loses speed on its own (air or water resistance). |
angularDamping | number | 0 | How fast it stops spinning on its own. |
At body build the runner reads these into a BodyDesc: velocity seeds the body's linear velocity, useGravity maps to gravityScale (1 on, 0 off), the dampings go straight across, and restitution goes on every collider attached to the body. When mass is set or centerOfMass is not zero, the body's mass properties are replaced after its colliders are attached: Rapier can move a centre of mass only as additional mass, so the colliders' density is set to 0 and the body carries the whole mass at the new centre, with the colliders' inertia scaled to it. A Collider without a RigidBody uses restitution 0.3. Friction is not on the RigidBody: it is the Collider's friction field (default 0.5).
The header checkbox does not switch it off
The physics runner ignores the RigidBody's enabled checkbox: an object with a disabled RigidBody is still built as a dynamic body. To make it non-dynamic, remove the component or mark the object Static. A Collider's checkbox does work: a disabled Collider builds no body at all.
Velocity and forces from scripts
Because velocity is read only at build time, a script sets and reads the live body through the API:
ts
const ball = api.spawn("Ball"); // a prefab with RigidBody + Collider
if (ball !== null) api.setVelocity(ball, 0, 4, -12);
const v = api.getVelocity(api.entity); // { x, y, z } after the last step, or nullsetVelocity is a no-op on an entity without a live dynamic body (fixed, Static, a character, or no physics this session); getVelocity returns null for one.
To drive a body with forces (a car, a boat, a thruster), push it with impulses. An impulse is a force times the time it acts, so a force F newtons applied every onFixedUpdate is F * dt. Given a world point, the impulse also turns the body, by its lever arm from the centre of mass:
ts
onFixedUpdate(api: ScriptApi, dt: number) {
const e = api.entity, m = api.getMass(e); // kg, or null without a live body
if (m === null) return;
// A spring holding a corner up: push at the corner, along the world up axis.
const corner = { x: 1, y: 0, z: 2 }; // world point
const v = api.getPointVelocity(e, corner.x, corner.y, corner.z)!; // its velocity, spin included
const force = 30000 * 0.1 - 2500 * v.y; // stiffness x compression - damping x speed
api.applyImpulse(e, 0, force * dt, 0, corner.x, corner.y, corner.z);
}| Call | What it does |
|---|---|
applyImpulse(e, x, y, z, px?, py?, pz?) | Push a dynamic body: through its centre of mass, or at a world point so it turns as well. |
getAngularVelocity(e) / setAngularVelocity(e, x, y, z) | Spin, in radians a second about each world axis. |
getPointVelocity(e, px, py, pz) | The velocity of the body at a world point, its spin included. |
getMass(e) | The body's mass in kg (RigidBody.mass, else from its colliders). |
teleport(e, x, y, z, rotation?) | Move the body to a new pose at once, its Transform with it. setPosition does not work on a dynamic body: the physics writes its own pose back next step. Velocity is kept; zero it with setVelocity and setAngularVelocity. |
Push once per fixed step, and turn on Project Settings ▸ Physics ▸ Fixed clock (physicsOnFixed): then each physics step runs right after onFixedUpdate, so every step gets exactly that step's impulses. With it off, physics steps once per frame and the number of fixed steps between two physics steps varies. Rapier applies an impulse at once, so a script that reads velocities and pushes in the same step should read them all first, then push.
Dynamic vs static - the deciding rule
Whether an entity becomes a dynamic body or a fixed (immovable) one is decided at Play start:
- Dynamic requires a
RigidBodyand that the object is not marked Static. - The Static checkbox in the Inspector header wins over everything. Marking an object Static forces a fixed body even if it carries a RigidBody - the same flag that enables draw-call batching and cached shadows also pins the object in the simulation. This is deliberate: it lets you keep authoring data on an object while treating it as scenery.
So the mental model is: RigidBody = "can move", Static = "never moves". If both are set, Static wins.
How poses flow back to the Transform
Each frame, after stepping the simulation, the runner walks the dynamic bodies and copies each one's new position and rotation back into its Transform:
Two things make this cheap:
- Only dynamic bodies get written back. Fixed bodies are never moved by the simulation, so they are skipped entirely, and they are not flagged as moved, so a 15,000-prop static scene never floods the render dirty-set.
- Settled bodies are skipped. If a body's pose is unchanged from its
Transformwithin1e-6(it has gone to sleep or simply didn't move this step), the runner writes nothing and doesn't mark it moved. Only the bodies that actually moved trigger a render re-sync.
Dynamic bodies are simulated and written back in local space - they behave as effectively root objects. Static colliders are placed at their full world transform (composed through parents) so a nested or imported collider lines up with its mesh.
With Project Settings → Physics → Fixed clock on, this write-back runs after every fixed step rather than once a frame; with it off, once a frame on the frame's dt. See Physics on the fixed clock.
In a 2D project (Project Settings → Physics → 2D) a dynamic body moves only in X and Y and turns only about Z. See 2D Games.
The all-static case
If a scene has no dynamic bodies, no active characters and no ragdolls, the physics step is skipped: fixed bodies can't collide with each other, so nothing can change. A scene of pure static scenery therefore spends no physics time per frame, unless a script ray-casts or moves a collider, which earns one step. The simulation wakes up by itself the moment you spawn a dynamic body (api.spawn) or a character starts moving. This is why marking scenery Static matters for performance.

Editing during Play
RigidBody and Collider are built into the simulation once, at Play start. Editing either component while playing triggers a soft re-sync before the next frame: the running sim is stopped and rebuilt in place from the current world so your change takes effect immediately. Dynamic bodies are rebuilt at their current pose, starting again from their velocity field; characters re-promote on their next moveAndSlide; scripts and animations are not reset.
See also
- Colliders & Shapes - give the body a shape to collide with.
- Physics Overview - body types, the runner lifecycle and the fixed clock.
- Static Batching - what the Static flag does for rendering.
- Scripting API -
setVelocity,getVelocityand the collision hooks.