mcpField
R
r3f-physics

r3f-physics

github.com/enzed开发1311.8k 次安装8 周前更新
代码仓库

关于 r3f-physics

r3f-physics 是面向 React Three Fiber 开发者的物理模拟指南,介绍 Rapier 刚体、碰撞体、力、时间步及碰撞事件。

主要功能

  1. 01刚体类型与碰撞体设置
  2. 02管理力与冲量
  3. 03物理时间步和渲染循环指导
  4. 04传感器、碰撞事件与关节
  5. 05角色控制器与模拟验证

适用场景

  1. 01添加下落且可点击的物体
  2. 02使用碰撞体构建静态环境
  3. 03通过关节连接刚体
  4. 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