The Jolt Physics Engine is a highly capable, real-time physics engine designed for games and VR applications, built for Horizon Forbidden West.
@react-three/jolt (or r3/jolt) is a wrapper library designed to slot seamlessly into a react-three-fiber pipeline. Jolt is very powerful and flexible, sometimes at the cost of usability — the goal of this library is to give you a world-class physics simulation without the complexity or the pitfalls.
pmndrs.github.io/react-three-jolt
| Introduction | what this is, and Jolt vs Rapier |
| Installation | peers, Vite, Next.js, Jolt build variants |
| Physics | the world component and every prop |
| RigidBody | bodies, BodyState, constraints, instancing |
| Shapes | autodetection, <Shape>, heightfields |
| Queries | raycasting, shapecasting, collide-shape |
| Collision groups | group and sub-group filtering |
| Controllers | character, camera rig, vehicles |
| Addons | input commands and helpers |
| Memory & lifecycle | who owns what in the WASM heap |
| SSR & Suspense | loading, error boundaries, Next.js |
| Migration | upgrading from the pre-2026 builds |
npm install @react-three/jolt jolt-physicsjolt-physics, @react-three/fiber (>=10), three (>=0.185) and react/react-dom (>=19) are peer dependencies — see Installation.
import { Canvas } from '@react-three/fiber';
import { Physics, RigidBody } from '@react-three/jolt';
import { Suspense } from 'react';
export function App() {
return (
<Canvas camera={{ position: [0, 5, 12] }}>
<Suspense fallback={null}>
<Physics gravity={[0, -9.81, 0]}>
<RigidBody position={[0, 8, 0]}>
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="hotpink" />
</mesh>
</RigidBody>
<RigidBody type="static" position={[0, -1, 0]}>
<mesh>
<boxGeometry args={[20, 1, 20]} />
<meshStandardMaterial color="#444" />
</mesh>
</RigidBody>
</Physics>
</Suspense>
<directionalLight position={[5, 10, 5]} />
<ambientLight intensity={0.4} />
</Canvas>
);
}<Physics> suspends while the Jolt WASM module loads, so it needs a <Suspense> boundary above it.
jolt-physics ships several builds (embedded wasm-compat, separate-file /wasm, debug and
multi-threaded variants). Pass an initializer to <Physics module> to pick one — see
Choosing a Jolt build
for the table and the Vite / Next.js recipes.
Jolt has two independent collision filters and they answer different questions.
Object layers (Layer in constants.ts) are the broad one: "what kind of thing is this" — moving, non-moving, kinematic, rig. They are pre-set in R3/Jolt (we plan to expose them later) and are what you would reach for to say "bullets never hit other bullets".
Collision groups are the narrow one: "should these two specific objects collide with each other". They are the right tool for a ragdoll whose upper arm shouldn't collide with its own torso, or a door that shouldn't collide with its own frame.
A body's collision group is a pair of numbers, a group and a subGroup:
- Two bodies with different
groupids always collide — the filter is skipped entirely. - Two bodies with the same
groupid consult the system-wide filter table, which decides based on theirsubGroupids. Every sub group pair collides until you turn one off.
Give every body inside a group its own subGroup id.
On the <RigidBody> component, with the group / subGroup props. Both are reactive — change them at any time and the body is updated (and woken) on the next step.
<RigidBody group={1} subGroup={2}>
<mesh>
<boxGeometry args={[5, 0.5, 8]} />
<meshStandardMaterial color="#ff4060" />
</mesh>
</RigidBody>Or from the BodySystem, either at creation or afterwards:
const handle = bodySystem.addBody(cubeMesh, { group: 1, subGroup: 2 });
const body = bodySystem.getBody(handle)!;
body.group = 1; // alias: body.collisionGroup
body.subGroup = 3; // alias: body.collisionSubGroupA body with no group set never pays for filtering, so only set one where you need it.
const { bodySystem } = physicsSystem;
bodySystem.disableCollision(2, 3); // sub groups 2 and 3 pass through each other
bodySystem.enableCollision(2, 3); // ...and back again
bodySystem.setGroupCollision(2, 3, false); // same thing, as one call
bodySystem.isCollisionEnabled(2, 3); // -> falseThis only affects bodies that share a group id. Two bodies in sub groups 2 and 3 but in different groups still collide.
Sub group ids index a fixed-size table, bodySystem.subGroupCount (default 256). Jolt does not bounds check that index in the release build, so R3/Jolt range checks every id and warns instead of letting it corrupt the heap. If you need more than the default, raise it before creating the first body that uses a group:
Subgroup 0 is the default and acts like most other physics systems. Any two Bodies in the same parent Group and Subgroup-0 will not collide with each other.
Bodies in Subgroup-0 will also ignore bodies in Subgroup-1.
(Green in the example. Note how when coming to a rest the cubes do not stack nicely, instead merge with each other)
| Doesnt Collide: | 0 | |||
|---|---|---|---|---|
| Collides: | 1 | 2 | Non-Members |
'Subgroup-1' is an addition made by R3/Jolt and the one we recommend using for any “standard” objects.
Filtering is often done to create trapdoors or filters but you still want the objects to collide with each other. This subgroup allows objects to access filters/traps but still act as regular bodies. (Besides green, all boxes in the example are in subgroup-1)
Doesn’t collide: Non Group Bodies Collides: All subgroups
| Doesnt Collide: | Non-Members | |||
|---|---|---|---|---|
| Collides: | 0 | 1 | 2 |
Subgroup-2 is best used as a block/filter device. Bodies in this subgroup ONLY collide with items in the same PARENT group. This means ALL OTHER bodies will ignore these bodies and fall right through them. However, items in the same “Group” will collide.
(The blue filter in the example is in subgroup-2)
There are 4 phases planned for this library. We are currently in Phase 0 (Pre-Alpha).
- Alpha: Stable Library — stabilize building, deployment and planning, with the minimum level of usability and performance.
- 1.0 Feature Parity — comparable with r3/rapier and use-cannon, with documentation and examples.
- 2.0 Advanced Jolt Features — pulleys, buoyancy, and the rest of what Jolt can do.
- 3.0 Kinematic Rigs — Jolt's skeleton animation system for rigid body models (ragdolls, characters).
See the Development Guide and the Contributing docs page.