关于 r3f-physics
r3f-physics 是面向 React Three Fiber 开发者的物理模拟指南,介绍 Rapier 刚体、碰撞体、力、时间步及碰撞事件。
主要功能
- 01刚体类型与碰撞体设置
- 02管理力与冲量
- 03物理时间步和渲染循环指导
- 04传感器、碰撞事件与关节
- 05角色控制器与模拟验证
适用场景
- 01添加下落且可点击的物体
- 02使用碰撞体构建静态环境
- 03通过关节连接刚体
- 04测试传感器和快速移动的刚体
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ enzed/ r3f-skills --skill r3f-physics安装后在 Claude Code 中输入/r3f-physics确认已加载。
附带文件references/controllers.md
详细介绍
React Three Fiber 物理
检查已安装的 Fiber、React 和 Rapier 版本。Rapier 2 面向 Fiber 9 / React 19;较旧的项目需要使用兼容的包版本线。将渲染与模拟的所有权分开。
下落并可点击的刚体
在带有灯光的 Canvas 下挂载。物理引擎会异步加载 WASM;请加入 Suspense。Cuboid 碰撞体参数是半尺寸,不同于 BoxGeometry 的完整尺寸。
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;速度运动学刚体使用线性/角速度 setter。 - 在 RigidBody 上设置初始变换。不要在
useFrame中为模拟中的网格设置动画位置;物理世界仍是权威来源,插值可能会覆盖该位置。 - 优先使用简单碰撞体或复合凸形状。三角网格主要用于静态凹形环境;凸包会封闭孔洞,无法保留任意凹形。
- 提供完整的手动碰撞体时,设置
colliders={false},否则也可能添加自动碰撞体。碰撞体的尺寸/变换必须与世界缩放一致;使用调试渲染检查碰撞体。 - 为碰撞体选择一致的密度/质量,并避免重叠的自动/手动碰撞体导致质量意外重复计算。
- 对于大量重复刚体,InstancedRigidBodies 可以降低渲染开销,但不会降低模拟每个刚体的成本。保持实例键和变换稳定。
力与模拟时间
- 冲量是一次性的动量变化。力会持续生效,直到重置;重复调用
addForce会累积。没有明确的力管理策略时,不要在每个渲染帧都添加相同的持续力。 - 使用
useBeforePhysicsStep处理必须与模拟刻对齐的输入/力。如果某个控制器负责某刚体的所有用户施加的力,它可以在每个模拟刻重置并重新施加;重置前应与其他力来源协调。 - 运动学目标应在物理步进时更新。使用
setTranslation传送与运动学移动不同,且可能绕过预期的碰撞响应。 - 优先使用固定时间步以获得稳定行为。
timeStep="vary"以牺牲可预测性换取可变步进;按渲染帧间隔缩放数值并不能让物理模拟变得确定。 - 对于按需渲染,使用
Physics updateLoop="independent",以便活动刚体请求渲染。休眠的物理世界不应强制进行不必要的渲染。 - 允许刚体进入休眠;应用需要唤醒刚体的操作时,显式唤醒。对于速度很快/体积很小且有隧穿风险的刚体,启用 CCD,但需考虑其开销。
事件、传感器与关节
- 传感器会报告交叠的进入/退出,不会产生接触响应。使用传感器交叠事件,不要期待普通碰撞事件。
- 碰撞组要求两个碰撞体的成员/筛选掩码兼容。除非需要该格式,否则请使用
interactionGroups,而不是手动构造掩码。 - 碰撞载荷可能没有对应独立碰撞体的 rigidBodyObject。请安全检查另一个碰撞体/刚体;不要假设每次碰撞到的都是有名称的网格。
- 遵循已安装 Rapier 的回调限制。在接触筛选钩子中,提前缓存刚体状态,不要在 Rust 借用的模拟状态中查询刚体状态。
- 关节使用局部锚点和轴连接刚体引用,而非世界坐标。检查钩子的具体元组形状,确认其适用于固定、旋转、球形、弹簧或绳索约束。
- 阅读受控运动与关节,了解步进对齐的运动学平台和正确对齐的铰链。
- 感知碰撞的角色控制器不同于移动网格或设置动态刚体的位置。请使用已安装 Rapier 的角色控制器 API,并测试台阶/斜坡/着地情况。
- 恢复世界快照需要匹配刚体的创建方式/句柄关系;这并非在现有 React 引用下替换任意场景的通用方法。
验证
检查静止接触、碰撞体对齐、冲量、休眠/唤醒,以及不同的渲染帧率。测试所用路径的传感器进入/退出、快速移动刚体穿透和 Strict Mode 重挂载。
来源
评论
支持 Markdown