PluginBench
Skill
Review
Audit score 70

r3f-physics

enzed/r3f-skills

Add Rapier physics simulation to React Three Fiber with rigid bodies, colliders, forces, and joints.

What is r3f-physics?

Integrates the Rapier physics engine into React Three Fiber scenes, enabling collision-driven movement, forces, and constraints. Use this for interactive 3D physics simulations; use animation guidance for purely visual motion without collision detection.

  • Mount Rapier Physics with dynamic and fixed rigid bodies that respond to forces and gravity
  • Apply impulses and forces to bodies, with control over momentum and continuous acceleration
  • Define colliders (cuboid, trimesh, hull, compound shapes) with proper density and mass management
  • Create joints (fixed, revolute, spherical, spring, rope) to connect bodies with local anchors and constraints
  • Use sensors to detect intersection enter/exit events without contact response
  • Manage kinematic bodies with setNextKinematicTranslation/Rotation or velocity setters for controlled motion

How to install r3f-physics

npx skills add https://github.com/enzed/r3f-skills --skill r3f-physics
Prerequisites
  • React Three Fiber 9+ and React 19+ (or compatible older versions with Rapier 1)
  • Rapier 2 package installed and WASM module available
  • Canvas with lighting and Suspense boundary for async Physics loading
Claude Code
Cursor
Windsurf
Cline

How to use r3f-physics

  1. 1.Install the skill and verify your Fiber, React, and Rapier versions match the target release
  2. 2.Wrap your scene content in a Physics component with a fixed timeStep (e.g., 1/60)
  3. 3.Create RigidBody components for dynamic objects, setting type, position, and colliders
  4. 4.Add CuboidCollider or other collider shapes with correct half-extent dimensions (not full dimensions)
  5. 5.Use useBeforePhysicsStep to apply forces or impulses aligned with simulation ticks
  6. 6.Test resting contact, collider alignment, and body behavior at different render frame rates

Use cases

Good for
  • Interactive 3D scenes where objects fall, collide, and respond to clicks or forces
  • Physics-based character controllers with proper grounding detection on stairs and slopes
  • Stacked or compound objects that require stable contact and sleeping optimization
  • Sensor-based triggers that detect when objects enter or exit regions without physical collision
  • Constrained mechanisms like hinges, springs, or ropes connecting multiple bodies
Who it's for
  • 3D web developers building interactive React Three Fiber applications
  • Game developers prototyping physics-driven mechanics in WebGL
  • Simulation creators needing stable, deterministic rigid-body dynamics
  • Developers familiar with Rapier or other physics engines seeking React integration

r3f-physics FAQ

Should I animate a physics body's position in useFrame?

No. The physics world is authoritative; do not animate a simulated mesh's position in useFrame, as interpolation can overwrite the physics result. Instead, let the RigidBody handle transforms and use forces/impulses for movement.

What is the difference between an impulse and a force?

An impulse is a one-time momentum change applied instantly. A force persists until reset; repeated addForce calls accumulate. Use impulses for discrete actions and forces for continuous effects managed per physics step.

Why are my colliders not aligned with my meshes?

Cuboid collider args are half-extents, while BoxGeometry args are full dimensions. Verify collider sizes and positions match your world scale using debug rendering, and ensure colliders={false} is set if you supply manual colliders.

How do I move a kinematic body?

Use setNextKinematicTranslation/Rotation for position-kinematic bodies or set linear/angular velocity for velocity-kinematic bodies. Avoid teleporting with setTranslation, which bypasses expected collision response.

What is the difference between sensors and collision events?

Sensors report intersection enter/exit without physical contact response. Use sensor intersection events rather than ordinary collision events for trigger-like behavior.

Full instructions (SKILL.md)

Source of truth, from enzed/r3f-skills.


name: r3f-physics description: Add Rapier rigid bodies, colliders, forces, sensors, and joints to React Three Fiber. Use for collision-driven movement and simulation; use animation guidance for purely visual motion.

React Three Fiber physics

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.

Falling and clickable body

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>
  )
}

Bodies and colliders

  • Dynamic bodies respond to forces. Fixed bodies represent static surfaces. Position-kinematic bodies use setNextKinematicTranslation/Rotation; velocity-kinematic bodies use linear/angular velocity setters.
  • Set initial transforms on RigidBody. Do not animate a simulated mesh's position in useFrame; the physics world remains authoritative and interpolation can overwrite it.
  • Prefer simple colliders or compound convex shapes. Use trimesh mainly for static concave environments; a hull closes holes and cannot preserve arbitrary concavity.
  • Set 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.
  • Choose collider density/mass consistently and avoid accidental duplicate mass from overlapping auto/manual colliders.
  • For many repeated bodies, InstancedRigidBodies reduces rendering overhead, not the cost of simulating each body. Keep instance keys/transforms stable.

Forces and simulation time

  • An impulse is a one-time momentum change. A force persists until reset; repeated addForce calls accumulate. Do not add the same continuous force every render frame without an explicit force-management strategy.
  • Use 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.
  • Kinematic targets should advance on physics steps. Teleporting with setTranslation is different from kinematic movement and can bypass expected collision response.
  • Prefer a fixed timestep for stable behavior. timeStep="vary" trades predictability for variable stepping; multiplying values by render delta does not make the physics deterministic.
  • For demand rendering, use Physics updateLoop="independent" so active bodies can request renders. A sleeping world should not force unnecessary rendering.
  • Let bodies sleep; explicitly wake them when applying actions that need it. Enable CCD for fast/small bodies when tunneling warrants its cost.

Events, sensors, and joints

  • Sensors report intersection enter/exit without contact response. Use sensor intersection events rather than expecting ordinary collision events.
  • Collision groups require compatible membership/filter masks on both colliders. Use interactionGroups instead of hand-building masks unless the format is needed.
  • Collision payloads may lack a rigidBodyObject for standalone colliders. Inspect the other collider/body safely; do not assume every hit is a named mesh.
  • Follow the installed Rapier callback restrictions. In contact-filter hooks, cache body state before the step rather than querying it during Rust's borrowed simulation state.
  • Joints connect body refs using local anchors and axes, not world coordinates. Check the hook's exact tuple shape for fixed, revolute, spherical, spring, or rope constraints.
  • Read controlled motion and joints for a step-aligned kinematic platform and correctly aligned hinge.
  • A collision-aware character controller is separate from moving a mesh or setting a dynamic body's position. Use the installed Rapier character-controller API and test stairs/slopes/grounding.
  • Restoring a world snapshot requires matching body creation/handle relationships; it is not a generic way to swap arbitrary scenes beneath existing React refs.

Verify

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.

Sources