Claude-skill-registry dev-r3f-r3f-physics
Physics integration with Rapier for R3F game development
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dev-r3f-r3f-physics" ~/.claude/skills/majiayu000-claude-skill-registry-dev-r3f-r3f-physics && rm -rf "$T"
manifest:
skills/data/dev-r3f-r3f-physics/SKILL.mdsource content
R3F Physics
"Physics makes games feel real – Rapier is fast and reliable."
When to Use This Skill
Use when:
- Adding physics simulation to objects
- Implementing collision detection
- Creating vehicles or character controllers
- Building interactive environments
Quick Start
import { Physics, RigidBody } from '@react-three/rapier'; function PhysicsScene() { return ( <Physics> {/* Falling cube */} <RigidBody> <mesh> <boxGeometry /> <meshStandardMaterial /> </mesh> </RigidBody> {/* Static floor */} <RigidBody type="fixed"> <mesh position={[0, -2, 0]}> <boxGeometry args={[10, 0.5, 10]} /> <meshStandardMaterial /> </mesh> </RigidBody> </Physics> ); }
Decision Framework
| Need | RigidBody Type |
|---|---|
| Player/Vehicle | |
| Ground/Walls | |
| Platforms (moving) | |
| Triggers | + sensor |
| Collision Shape | Use For |
|---|---|
| Boxes, buildings |
| Spheres, wheels |
| Characters |
| Complex convex shapes |
| Complex concave (static only) |
Progressive Guide
Level 1: Basic Physics
import { Physics, RigidBody } from '@react-three/rapier'; function BasicPhysics() { return ( <Physics gravity={[0, -9.81, 0]}> {/* Dynamic body - affected by physics */} <RigidBody position={[0, 5, 0]}> <mesh> <boxGeometry /> <meshStandardMaterial color="red" /> </mesh> </RigidBody> {/* Fixed body - doesn't move */} <RigidBody type="fixed"> <mesh position={[0, -1, 0]} rotation={[-Math.PI / 2, 0, 0]}> <planeGeometry args={[20, 20]} /> <meshStandardMaterial color="green" /> </mesh> </RigidBody> </Physics> ); }
Level 2: Collision Events
import { RigidBody } from '@react-three/rapier'; function CollisionBox() { const handleCollisionEnter = (event) => { console.log('Collision with:', event.colliderObject); }; const handleCollisionExit = (event) => { console.log('Collision ended with:', event.colliderObject); }; return ( <RigidBody onCollisionEnter={handleCollisionEnter} onCollisionExit={handleCollisionExit}> <mesh> <boxGeometry /> <meshStandardMaterial /> </mesh> </RigidBody> ); }
Level 3: Sensors (Triggers)
import { RigidBody, CuboidCollider } from '@react-three/rapier'; function TriggerZone() { const handleIntersection = (event) => { console.log('Something entered the zone!'); }; return ( <RigidBody type="fixed"> <CuboidCollider args={[2, 2, 2]} sensor onIntersectionEnter={handleIntersection} /> {/* Visual representation (optional) */} <mesh> <boxGeometry args={[4, 4, 4]} /> <meshStandardMaterial color="blue" transparent opacity={0.3} /> </mesh> </RigidBody> ); }
Level 4: Applying Forces
import { useRef } from 'react'; import { RigidBody, RapierRigidBody } from '@react-three/rapier'; import { useFrame } from '@react-three/fiber'; function JumpingBall() { const rigidBodyRef = useRef<RapierRigidBody>(null); const jump = () => { rigidBodyRef.current?.applyImpulse({ x: 0, y: 10, z: 0 }, true); }; useFrame(() => { // Apply continuous force (e.g., for movement) // rigidBodyRef.current?.applyForce({ x: 5, y: 0, z: 0 }, true); }); return ( <RigidBody ref={rigidBodyRef} onClick={jump}> <mesh> <sphereGeometry /> <meshStandardMaterial color="orange" /> </mesh> </RigidBody> ); }
Level 5: Vehicle Physics
import { useRef } from 'react'; import { RigidBody, useRapier } from '@react-three/rapier'; import { useFrame } from '@react-three/fiber'; function Vehicle() { const chassisRef = useRef(); const { rapier, world } = useRapier(); useFrame(() => { if (!chassisRef.current) return; // Get velocity const vel = chassisRef.current.linvel(); const speed = Math.sqrt(vel.x ** 2 + vel.z ** 2); // Apply steering based on input // ... implement steering logic }); return ( <RigidBody ref={chassisRef} colliders="cuboid" mass={1500} linearDamping={0.5} angularDamping={0.5} > <mesh> <boxGeometry args={[2, 0.5, 4]} /> <meshStandardMaterial color="blue" /> </mesh> </RigidBody> ); }
Collision Groups
// Define collision groups (bitmask) const GROUPS = { PLAYER: 0b0001, ENEMY: 0b0010, GROUND: 0b0100, PROJECTILE: 0b1000, }; // Player collides with ground and enemy, not projectiles <RigidBody collisionGroups={interactionGroups( GROUPS.PLAYER, GROUPS.GROUND | GROUPS.ENEMY )} >
Anti-Patterns
DON'T:
- Use
for dynamic bodies (not supported)trimesh - Apply forces every frame without deltaTime
- Create/destroy RigidBodies frequently
- Use physics for non-interactive decorations
- Ignore collision layers (performance)
DO:
- Use appropriate collider shapes (simpler = faster)
- Use
for static environmentfixed - Pool physics objects when possible
- Use collision groups for filtering
- Dispose physics world on scene change
Physics Debugging
import { Physics, Debug } from '@react-three/rapier'; function DebugScene() { return ( <Physics> <Debug /> {/* Shows collision shapes */} {/* Your physics objects */} </Physics> ); }
Checklist
Before implementing physics:
- Appropriate RigidBody type selected
- Collision shapes match visual reasonably
- Collision groups configured
- Events handled (if needed)
- Forces scaled by deltaTime
- Physics debug visualized during development
Reference
- Rapier documentation
- @react-three/rapier docs
— R3F basicsdeveloper/r3f/r3f-fundamentals.md