React Three Fiber physics with Rapier - RigidBody, colliders, forces, joints, sensors...
Check installed Fiber, React, and Rapier versions. Rapier 2 targets Fiber 9 / React 19; older projects need their compatible package line. Keep rendering and simulation ownership separate.
Mount beneath Canvas with lighting. Physics loads WASM asynchronously; include Suspense. Cuboid collider arguments are half-extents, unlike BoxGeometry's full dimensions.
import { Suspense, useRef } from 'react'
import { CuboidCollider, Physics, RigidBody, type RapierRigidBody } from '@react-three/rapier'
function FallingBox() {
const body = useRef<RapierRigidBody>(null)
return (
<RigidBody ref={body} position={[0, 2, 0]} colliders="cuboid" restitution={0.2}>
<mesh name="physics-box" onClick={() => body.current?.applyImpulse({ x: 0, y: 3, z: 0 }, true)}>
<boxGeometry />
<meshStandardMaterial color="coral" />
</mesh>
</RigidBody>
)
}
export default function Example() {
return (
<Suspense fallback={null}>
<Physics timeStep={1 / 60}>
<FallingBox />
<RigidBody type="fixed" colliders={false}>
<CuboidCollider args={[4, 0.25, 4]} position={[0, -0.25, 0]} />
<mesh position={[0, -0.25, 0]}>
<boxGeometry args={[8, 0.5, 8]} />
<meshStandardMaterial color="slategray" />
</mesh>
</RigidBody>
</Physics>
</Suspense>
)
}
setNextKinematicTranslation/Rotation; velocity-kinematic bodies use linear/angular velocity setters.useFrame; the physics world remains authoritative and interpolation can overwrite it.colliders={false} when supplying complete manual colliders, otherwise automatic colliders may be added as well. Collider sizes/transforms must match world scale; use debug rendering to inspect them.addForce calls accumulate. Do not add the same continuous force every render frame without an explicit force-management strategy.useBeforePhysicsStep for input/forces that must align with simulation ticks. If a controller owns all user forces on a body, it can reset and reapply them per tick; coordinate with other force sources before resetting.setTranslation is different from kinematic movement and can bypass expected collision response.timeStep="vary" trades predictability for variable stepping; multiplying values by render delta does not make the physics deterministic.Physics updateLoop="independent" so active bodies can request renders. A sleeping world should not force unnecessary rendering.interactionGroups instead of hand-building masks unless the format is needed.Check resting contact, collider alignment, impulses, sleeping/waking, and different render frame rates. Test sensor enter/exit, fast-body tunneling, and Strict Mode remounts for the paths used.