# RigidBodyComponentSystem

Class · extends [`ComponentSystem`](https://api.playcanvas.com/engine/classes/ComponentSystem.md) · category: Physics

Source: https://github.com/playcanvas/engine/blob/f059dc005842f76e052cdf44d8370c8c7ec475ac/src/framework/components/rigid-body/system.js#L74

The RigidBodyComponentSystem manages the physics simulation for all rigid body components
in the application and is accessed as `app.systems.rigidbody`. It owns the physics world,
creates and destroys the bodies behind rigid body and collision components, steps the
simulation once per frame and writes the resulting transforms back to their entities. It also
holds global settings such as [RigidBodyComponentSystem#gravity](https://api.playcanvas.com/engine/classes/RigidBodyComponentSystem.md#gravity), performs raycasts
and reports collisions.

The system is only functional once a physics backend is installed: either by supplying
[AppOptions#physicsWorld](https://api.playcanvas.com/engine/classes/AppOptions.md#physicsworld) when creating the application, or automatically when the
application has loaded the Ammo.js [WasmModule](https://api.playcanvas.com/engine/classes/WasmModule.md). Use a recent Ammo.js build: mesh
colliders only follow entity scale with a build that exposes `btScaledBvhTriangleMeshShape`.

Set [RigidBodyComponentSystem#timeScale](https://api.playcanvas.com/engine/classes/RigidBodyComponentSystem.md#timescale) to slow the simulation down, speed it up or
pause it, for example while a pause menu is open, and call
[RigidBodyComponentSystem#step](https://api.playcanvas.com/engine/classes/RigidBodyComponentSystem.md#step) to advance it manually.

## Properties

### gravity

```ts
gravity: Vec3
```

The world space vector representing global gravity in the physics simulation. Defaults to
[0, -9.81, 0] which is an approximation of the gravitational force on Earth.

The value is applied to the physics backend at the start of the next step, whether the
vector is modified in place or replaced with a new one.

**Example**

```ts
// Set the gravity in the physics world to simulate a planet with low gravity
app.systems.rigidbody.gravity = new Vec3(0, -3.7, 0);
```

### timeScale

```ts
timeScale: number = 1
```

Scales the time the simulation is advanced by each frame. Defaults to 1. Values below 1
run physics in slow motion and values above 1 speed it up. 0 pauses the simulation: the
system stops advancing it, bodies freeze in place, entity transforms are no longer driven
by their bodies and no contact or trigger events fire. The rest of the application keeps
running, so this suits a pause menu or inventory screen that must stay interactive while
the game world stands still. Negative values are treated as 0.

This scale is applied on top of [AppBase#timeScale](https://api.playcanvas.com/engine/classes/AppBase.md#timescale). The simulation can still be
advanced manually with [RigidBodyComponentSystem#step](https://api.playcanvas.com/engine/classes/RigidBodyComponentSystem.md#step) while paused, for example to
drive it from a custom time source.

How slow motion below one fixed substep per frame looks depends on the backend: the Ammo
backend interpolates body transforms between substeps so motion stays smooth, while other
backends may only move bodies on the frames in which a substep runs. Fast forward is
limited by the maximum number of substeps the simulation may take per frame, beyond which
it runs slower than requested.

Forces applied with [RigidBodyComponent#applyForce](https://api.playcanvas.com/engine/classes/RigidBodyComponent.md#applyforce) while paused accumulate on the
body and are applied together on the next step, because forces are only cleared when the
simulation steps. Impulses and velocity changes take effect immediately.

**Example**

```ts
// Freeze the game world while the pause menu is open
app.systems.rigidbody.timeScale = 0;
```

**Example**

```ts
// Run physics at quarter speed for a slow motion effect
app.systems.rigidbody.timeScale = 0.25;
```

## Accessors

### physicsWorld

```ts
get physicsWorld(): PhysicsWorld | null
```

Gets the installed physics backend, or null when no backend is installed. Supply a
backend via [AppOptions#physicsWorld](https://api.playcanvas.com/engine/classes/AppOptions.md#physicsworld), or load the Ammo.js library to have one
installed automatically.

## Methods

### raycastAll

```ts
raycastAll(start: Vec3, end: Vec3, options?: object): RaycastResult[]
```

Raycast the world and return all entities the ray hits. It returns an array of
[RaycastResult](https://api.playcanvas.com/engine/classes/RaycastResult.md), one for each hit. If no hits are detected, the returned array will be
of length 0. Results are returned in no particular order unless `options.sort` is true, in
which case they are sorted by distance with the closest first.

**Parameters**

- `start` ([`Vec3`](https://api.playcanvas.com/engine/classes/Vec3.md)): The world space point where the ray starts.
- `end` ([`Vec3`](https://api.playcanvas.com/engine/classes/Vec3.md)): The world space point where the ray ends.
- `options` (`object`, optional, default `{}`): The additional options for the raycasting.
    - `options.filterCallback` (`Function`, optional): Custom function to use to filter entities.
      Must return true to proceed with result. Takes the entity to evaluate as argument.
    - `options.filterCollisionGroup` (`number`, optional): Collision group to apply to the raycast.
    - `options.filterCollisionMask` (`number`, optional): Collision mask to apply to the raycast.
    - `options.filterTags` (`any[]`, optional): Tags filters. Defined the same way as a [Tags#has](https://api.playcanvas.com/engine/classes/Tags.md#has)
      query but within an array.
    - `options.hitBackFaces` (`boolean`, optional): Whether the ray can hit the back faces of mesh
      colliders, which face away from the ray: the far side of a closed mesh, or the first surface
      met by a ray starting inside one. A back-face hit reports a normal flipped to face the start
      of the ray. Other collision shapes never report back-face hits. Defaults to true.
    - `options.sort` (`boolean`, optional): Whether to sort raycast results based on distance with closest
      first. Defaults to false.

**Returns** [`RaycastResult`](https://api.playcanvas.com/engine/classes/RaycastResult.md)`[]`: An array of raycast hit results (0 length if there were no hits
or no physics backend is installed).

**Example**

```ts
// Return all results of a raycast between 0, 2, 2 and 0, -2, -2
const hits = this.app.systems.rigidbody.raycastAll(new Vec3(0, 2, 2), new Vec3(0, -2, -2));
```

**Example**

```ts
// Return all results of a raycast between 0, 2, 2 and 0, -2, -2
// where hit entity is tagged with `bird` OR `mammal`
const hits = this.app.systems.rigidbody.raycastAll(new Vec3(0, 2, 2), new Vec3(0, -2, -2), {
    filterTags: [ "bird", "mammal" ]
});
```

**Example**

```ts
// Return all results of a raycast between 0, 2, 2 and 0, -2, -2
// where hit entity has a `camera` component
const hits = this.app.systems.rigidbody.raycastAll(new Vec3(0, 2, 2), new Vec3(0, -2, -2), {
    filterCallback: (entity) => entity && entity.camera
});
```

**Example**

```ts
// Return all results of a raycast between 0, 2, 2 and 0, -2, -2, skipping the back faces
// of mesh colliders so a ray through a closed mesh hits it only where it enters
const hits = this.app.systems.rigidbody.raycastAll(new Vec3(0, 2, 2), new Vec3(0, -2, -2), {
    hitBackFaces: false
});
```

**Example**

```ts
// Return all results of a raycast between 0, 2, 2 and 0, -2, -2
// where hit entity is tagged with (`carnivore` AND `mammal`) OR (`carnivore` AND `reptile`)
// and the entity has an `anim` component
const hits = this.app.systems.rigidbody.raycastAll(new Vec3(0, 2, 2), new Vec3(0, -2, -2), {
    filterTags: [
        [ "carnivore", "mammal" ],
        [ "carnivore", "reptile" ]
    ],
    filterCallback: (entity) => entity && entity.anim
});
```

### raycastFirst

```ts
raycastFirst(start: Vec3, end: Vec3, options?: object): RaycastResult | null
```

Raycast the world and return the first entity the ray hits. Fire a ray into the world from
start to end, if the ray hits an entity with a collision component, it returns a
[RaycastResult](https://api.playcanvas.com/engine/classes/RaycastResult.md), otherwise returns null.

**Parameters**

- `start` ([`Vec3`](https://api.playcanvas.com/engine/classes/Vec3.md)): The world space point where the ray starts.
- `end` ([`Vec3`](https://api.playcanvas.com/engine/classes/Vec3.md)): The world space point where the ray ends.
- `options` (`object`, optional, default `{}`): The additional options for the raycasting.
    - `options.filterCallback` (`Function`, optional): Custom function to use to filter entities.
      Must return true to proceed with result. Takes one argument: the entity to evaluate.
    - `options.filterCollisionGroup` (`number`, optional): Collision group to apply to the raycast.
    - `options.filterCollisionMask` (`number`, optional): Collision mask to apply to the raycast.
    - `options.filterTags` (`any[]`, optional): Tags filters. Defined the same way as a [Tags#has](https://api.playcanvas.com/engine/classes/Tags.md#has)
      query but within an array.
    - `options.hitBackFaces` (`boolean`, optional): Whether the ray can hit the back faces of mesh
      colliders, which face away from the ray: the far side of a closed mesh, or the first surface
      met by a ray starting inside one. A back-face hit reports a normal flipped to face the start
      of the ray. Other collision shapes never report back-face hits. Defaults to true.

**Returns** [`RaycastResult`](https://api.playcanvas.com/engine/classes/RaycastResult.md) `| null`: The result of the raycasting, or null if there was no hit or
no physics backend is installed.

### step

```ts
step(dt: number): void
```

Advances the physics simulation by dt seconds. Synchronizes triggers, compound shapes and
kinematic bodies from their entities, steps the backend in fixed-length substeps (up to a
maximum number per call), writes the resulting transforms of dynamic bodies back to their
entities and fires contact and trigger events.

The system calls this once per frame with the frame delta time multiplied by
[RigidBodyComponentSystem#timeScale](https://api.playcanvas.com/engine/classes/RigidBodyComponentSystem.md#timescale), unless that is 0. Call it directly to step the
simulation manually: to advance it while paused, to fast forward it by stepping several
times in one frame, or to drive it from a custom time source. Automatic stepping continues
while timeScale is above 0, so calling this every frame as well advances the simulation
twice per frame. Set timeScale to 0 first when taking over stepping entirely. The delta is
used as given, without applying timeScale. Does nothing when no physics backend is
installed.

**Parameters**

- `dt` (`number`): The amount of time to advance the simulation by, in seconds.

**Example**

```ts
// Pause automatic stepping and advance the simulation by 1/60 s per key press
const physics = app.systems.rigidbody;
physics.timeScale = 0;
app.keyboard.on('keydown', (event) => {
    if (event.key === KEY_SPACE) {
        physics.step(1 / 60);
    }
});
```

## Events

### EVENT_CONTACT

```ts
static EVENT_CONTACT: string = 'contact'
```

Fired when a contact occurs between two rigid bodies. The handler is passed a
[SingleContactResult](https://api.playcanvas.com/engine/classes/SingleContactResult.md) object containing details of the contact between the two bodies.

**Example**

```ts
app.systems.rigidbody.on('contact', (result) => {
    console.log(`Contact between ${result.a.name} and ${result.b.name}`);
});
```

## Inherited from [ComponentSystem](https://api.playcanvas.com/engine/classes/ComponentSystem.md)

- `fire(name: string, arg1?: any, arg2?: any, arg3?: any, arg4?: any, arg5?: any, arg6?: any, arg7?: any, arg8?: any): EventHandler`
- `hasEvent(name: string): boolean`
- `off(name?: string, callback?: HandleEventCallback, scope?: any): EventHandler`
- `on(name: string, callback: HandleEventCallback, scope?: any): EventHandle`
- `once(name: string, callback: HandleEventCallback, scope?: any): EventHandle`
