---
name: r3f-physics
description: React Three Fiber physics with Rapier - RigidBody, colliders, forces, joints, sensors. Use when adding physics simulation, collision detection, character controllers, or creating interactive physics-based experiences.
---
# React Three Fiber Physics (Rapier)
## Quick Start
```tsx
import { Canvas } from '@react-three/fiber'
import { Physics, RigidBody, CuboidCollider } from '@react-three/rapier'
import { Suspense } from 'react'
function Scene() {
return (
)
}
```
## Installation
```bash
npm install @react-three/rapier
```
## Physics Component
The root component that creates the physics world.
```tsx
import { Physics } from '@react-three/rapier'
```
### On-Demand Rendering
For performance optimization with static scenes:
```tsx
```
## RigidBody
Makes objects participate in physics simulation.
### Basic Usage
```tsx
import { RigidBody } from '@react-three/rapier'
// Dynamic body (affected by forces/gravity)
// Fixed body (immovable)
// Kinematic body (moved programmatically)
```
### RigidBody Types
| Type | Description |
|------|-------------|
| `dynamic` | Affected by forces, gravity, collisions (default) |
| `fixed` | Immovable, infinite mass |
| `kinematicPosition` | Moved via setNextKinematicTranslation |
| `kinematicVelocity` | Moved via setNextKinematicRotation |
### RigidBody Properties
```tsx
```
## Colliders
### Automatic Colliders
RigidBody auto-generates colliders from child meshes:
```tsx
// Global default
{/* Gets hull collider */}
// Per-body override
```
### Collider Types
| Type | Description | Best For |
|------|-------------|----------|
| `cuboid` | Box shape | Boxes, crates |
| `ball` | Sphere shape | Balls, spherical objects |
| `hull` | Convex hull | Complex convex shapes |
| `trimesh` | Triangle mesh | Concave/complex static geometry |
### Manual Colliders
```tsx
import {
CuboidCollider,
BallCollider,
CapsuleCollider,
CylinderCollider,
ConeCollider,
HeightfieldCollider,
TrimeshCollider,
ConvexHullCollider
} from '@react-three/rapier'
// Standalone collider (static)
// Inside RigidBody (compound collider)
{/* Additional colliders */}
// Collider args reference
```
### Mesh Colliders
For complex shapes:
```tsx
import { MeshCollider } from '@react-three/rapier'
// Convex hull for dynamic bodies
```
## Applying Forces
### Using Refs
```tsx
import { RigidBody, RapierRigidBody } from '@react-three/rapier'
import { useRef, useEffect } from 'react'
function ForcefulBox() {
const rigidBody = useRef(null)
useEffect(() => {
if (rigidBody.current) {
// One-time impulse (instantaneous)
rigidBody.current.applyImpulse({ x: 0, y: 10, z: 0 }, true)
// Continuous force (apply each frame)
rigidBody.current.addForce({ x: 0, y: 10, z: 0 }, true)
// Torque (rotation)
rigidBody.current.applyTorqueImpulse({ x: 0, y: 5, z: 0 }, true)
rigidBody.current.addTorque({ x: 0, y: 5, z: 0 }, true)
}
}, [])
return (
)
}
```
### In useFrame
```tsx
import { useFrame } from '@react-three/fiber'
function ContinuousForce() {
const rigidBody = useRef(null)
useFrame(() => {
if (rigidBody.current) {
// Apply force every frame
rigidBody.current.addForce({ x: 0, y: 20, z: 0 }, true)
}
})
return (
)
}
```
### Getting/Setting Position
```tsx
import { vec3, quat, euler } from '@react-three/rapier'
function PositionControl() {
const rigidBody = useRef(null)
const teleport = () => {
if (rigidBody.current) {
// Get current transform
const position = vec3(rigidBody.current.translation())
const rotation = quat(rigidBody.current.rotation())
// Set new transform
rigidBody.current.setTranslation({ x: 0, y: 10, z: 0 }, true)
rigidBody.current.setRotation({ x: 0, y: 0, z: 0, w: 1 }, true)
// Set velocities
rigidBody.current.setLinvel({ x: 0, y: 0, z: 0 }, true)
rigidBody.current.setAngvel({ x: 0, y: 0, z: 0 }, true)
}
}
return (
)
}
```
## Collision Events
### On RigidBody
```tsx
{
console.log('Collision with', other.rigidBodyObject?.name)
console.log('Contact point', manifold.solverContactPoint(0))
}}
onCollisionExit={({ target, other }) => {
console.log('Collision ended with', other.rigidBodyObject?.name)
}}
onContactForce={({ totalForce }) => {
console.log('Contact force:', totalForce)
}}
onSleep={() => console.log('Body went to sleep')}
onWake={() => console.log('Body woke up')}
>
```
### On Colliders
```tsx
console.log('Collider hit')}
onCollisionExit={(payload) => console.log('Collider exit')}
/>
```
## Sensors
Detect overlaps without physical collision:
```tsx
{/* Visible mesh */}
{/* Invisible sensor trigger */}
console.log('Entered trigger zone')}
onIntersectionExit={() => console.log('Exited trigger zone')}
/>
// Goal detection example
console.log('Goal!')}
/>
```
## Collision Groups
Control which objects can collide:
```tsx
import { interactionGroups } from '@react-three/rapier'
// Group 0, interacts with groups 0, 1, 2
// Group 12, interacts with all groups
// Groups 0 and 5, only interacts with group 7
// On RigidBody (applies to all auto-generated colliders)
...
```
## Joints
Connect rigid bodies together.
### Fixed Joint
Bodies don't move relative to each other:
```tsx
import { useFixedJoint, RapierRigidBody } from '@react-three/rapier'
function FixedJointExample() {
const bodyA = useRef(null)
const bodyB = useRef(null)
useFixedJoint(bodyA, bodyB, [
[0, 0, 0], // Position in bodyA's local space
[0, 0, 0, 1], // Orientation in bodyA's local space (quaternion)
[0, -1, 0], // Position in bodyB's local space
[0, 0, 0, 1], // Orientation in bodyB's local space
])
return (
<>
>
)
}
```
### Revolute Joint (Hinge)
Rotation around one axis:
```tsx
import { useRevoluteJoint } from '@react-three/rapier'
function HingeDoor() {
const frame = useRef(null)
const door = useRef(null)
useRevoluteJoint(frame, door, [
[0.5, 0, 0], // Joint position in frame's local space
[-0.5, 0, 0], // Joint position in door's local space
[0, 1, 0], // Rotation axis
])
return (
<>
>
)
}
```
### Spherical Joint (Ball-Socket)
Rotation in all directions:
```tsx
import { useSphericalJoint } from '@react-three/rapier'
function BallJoint() {
const bodyA = useRef(null)
const bodyB = useRef(null)
useSphericalJoint(bodyA, bodyB, [
[0, -0.5, 0], // Position in bodyA's local space
[0, 0.5, 0], // Position in bodyB's local space
])
return (
<>
>
)
}
```
### Prismatic Joint (Slider)
Translation along one axis:
```tsx
import { usePrismaticJoint } from '@react-three/rapier'
function Slider() {
const track = useRef(null)
const slider = useRef(null)
usePrismaticJoint(track, slider, [
[0, 0, 0], // Position in track's local space
[0, 0, 0], // Position in slider's local space
[1, 0, 0], // Axis of translation
])
return (
<>
>
)
}
```
### Spring Joint
Elastic connection:
```tsx
import { useSpringJoint } from '@react-three/rapier'
function SpringConnection() {
const anchor = useRef(null)
const ball = useRef(null)
useSpringJoint(anchor, ball, [
[0, 0, 0], // Position in anchor's local space
[0, 0, 0], // Position in ball's local space
2, // Rest length
1000, // Stiffness
10, // Damping
])
return (
<>
>
)
}
```
### Rope Joint
Maximum distance constraint:
```tsx
import { useRopeJoint } from '@react-three/rapier'
function RopeConnection() {
const anchor = useRef(null)
const weight = useRef(null)
useRopeJoint(anchor, weight, [
[0, 0, 0], // Position in anchor's local space
[0, 0, 0], // Position in weight's local space
3, // Max distance (rope length)
])
return (
<>
>
)
}
```
### Motorized Joints
```tsx
import { useRevoluteJoint } from '@react-three/rapier'
import { useFrame } from '@react-three/fiber'
function MotorizedWheel({ bodyA, bodyB }) {
const joint = useRevoluteJoint(bodyA, bodyB, [
[0, 0, 0],
[0, 0, 0],
[0, 0, 1], // Rotation axis
])
useFrame(() => {
if (joint.current) {
// Configure motor: velocity, damping
joint.current.configureMotorVelocity(10, 2)
}
})
return null
}
```
## Instanced Physics
Efficient physics for many identical objects:
```tsx
import { InstancedRigidBodies, RapierRigidBody } from '@react-three/rapier'
import { useRef, useMemo } from 'react'
function InstancedBalls() {
const COUNT = 100
const rigidBodies = useRef(null)
const instances = useMemo(() => {
return Array.from({ length: COUNT }, (_, i) => ({
key: `ball-${i}`,
position: [
(Math.random() - 0.5) * 10,
Math.random() * 10 + 5,
(Math.random() - 0.5) * 10,
] as [number, number, number],
rotation: [0, 0, 0] as [number, number, number],
}))
}, [])
return (
)
}
```
## Accessing the World
```tsx
import { useRapier } from '@react-three/rapier'
import { useEffect } from 'react'
function WorldAccess() {
const { world, rapier } = useRapier()
useEffect(() => {
// Change gravity
world.setGravity({ x: 0, y: -20, z: 0 })
// Iterate over bodies
world.bodies.forEach((body) => {
console.log(body.translation())
})
}, [world])
return null
}
```
### Manual Stepping
```tsx
function ManualStep() {
const { step } = useRapier()
const advancePhysics = () => {
step(1 / 60) // Advance by one frame
}
return
}
```
### World Snapshots
Save and restore physics state:
```tsx
function SnapshotSystem() {
const { world, setWorld, rapier } = useRapier()
const snapshot = useRef()
const saveState = () => {
snapshot.current = world.takeSnapshot()
}
const loadState = () => {
if (snapshot.current) {
setWorld(rapier.World.restoreSnapshot(snapshot.current))
}
}
return (
<>
>
)
}
```
## Attractors
From `@react-three/rapier-addons`:
```tsx
import { Attractor } from '@react-three/rapier-addons'
// Attract nearby bodies
// Repel bodies
// Selective attraction (only affect certain groups)
```
## Debug Visualization
```tsx
{/* All colliders shown as wireframes */}
// Conditional debug
...
```
## Performance Tips
1. **Use appropriate collider types**: `cuboid` and `ball` are fastest
2. **Avoid `trimesh` for dynamic bodies**: Use `hull` instead
3. **Enable sleeping**: Bodies at rest stop computing
4. **Use collision groups**: Reduce collision checks
5. **Limit active bodies**: Too many dynamic bodies hurts performance
6. **Use instanced bodies**: For many identical objects
7. **Fixed timestep**: More stable than variable
```tsx
// Performance-optimized setup
{/* Use collision groups to limit checks */}
...
```
## See Also
- `r3f-fundamentals` - R3F basics and hooks
- `r3f-interaction` - User input and controls
- `r3f-animation` - Combining physics with animation