UE5.8 Rigid Body 与 Physics Constraint

📑 目录

UE5.8 Rigid Body 与 Physics Constraint

一、从一座被围攻的城堡说起

老赵接到了一个中世纪攻城 demo:城门要能被撞锤撞开,吊桥要能靠绞盘放下,守军被击飞后要在台阶上滚落,城墙上的投石机械臂要能按节奏把石块抛出去。策划只给了四个字——“要真实感”。

他先在场景里摆了几个 Static Mesh,打开 Simulate Physics,发现箱子确实会掉下来,可一旦涉及门轴、链条、人体瘫倒这些需要“连接”的物体,事情就开始复杂。门扇要么原地乱抖,要么一撞就飞;吊桥放下时像块铁片直接拍在地上;敌人中箭后要么笔直倒下,要么四肢扭曲成奇怪的角度;机械臂倒是能转,可抓取和释放的时机完全对不上。

这些问题的根子都在 Rigid Body 与 Physics Constraint 的搭配方式上。老赵花了一周把 PhysX 5 在 UE5.8 中的这套接口重新过了一遍,demo 才算稳定跑起来。下面是他整理出来的要点。

二、Rigid Body 组件:先让物体“硬”起来

2.1 Static Mesh 的物理开关

在 UE5.8 的 Content Browser 里选中一个 Static Mesh,Details 面板里勾选 Enable Full Precision UVs 不一定必要,但 Collision ComplexitySimple Collision 必须提前建好。没有碰撞体的网格在世界里可以渲染,但 Simulate Physics 不会生效。

把网格拖进关卡后,Details > Physics > Simulate Physics 勾选上,这个 Actor 就拥有了 Rigid Body。此时它受重力、碰撞、冲量影响。Mass 默认按材质密度和 Simple Collision 体积自动计算,单位为千克。老赵发现一块城门木板被算成八百多公斤,这是因为 Convex Decomposition 的分辨率过高导致体积膨胀,改小 Hull Count 和 Max Hull Vertices 后回到合理范围。

2.2 Rigid Body 组件 vs Primitive Component

Blueprint 里常见的 Static Mesh Component 继承自 Primitive Component。Rigid Body 组件(UStaticMeshComponent::BodyInstance)并不是额外挂一个子组件,而是每个 Primitive 自带的 FBodyInstance。真正在物理世界里注册的是 FBodyInstance 对应的 FKAggregateGeomFPhysicsActorHandle

下面这张图展示了 Actor 与物理引擎层级之间的结构。

architecture-beta
    group actor[关卡中的可物理化 Actor]
        service root[Root Component] in actor
        service mesh[Static Mesh Component] in actor
        service body[FBodyInstance] in mesh
    group engine[物理引擎层]
        service handle[Physics Actor Handle] in engine
        service geom[Collision Geometry] in engine
        service solver[PhysX 5 Solver] in engine
    root --> mesh
    mesh --> body
    body --> handle
    handle --> geom
    geom --> solver

2.3 质量、重心与惯性张量

PhysX 5 里的刚体运动方程大致可写成:

\begin{aligned} m \ddot{\mathbf{x}} &= \mathbf{F}_{\text{ext}} + \mathbf{F}_{\text{constraint}} \\ \mathbf{I} \dot{\boldsymbol{\omega}} + \boldsymbol{\omega} \times (\mathbf{I} \boldsymbol{\omega}) &= \boldsymbol{\tau}_{\text{ext}} + \boldsymbol{\tau}_{\text{constraint}} \end{aligned}

其中 mm 是质量,I\mathbf{I} 是惯性张量。UE5.8 默认把 I\mathbf{I} 交给物理引擎根据碰撞体自动估算。如果门的摆动看起来太轻飘,可以手动勾选 Override Mass 并把 Mass 调高;如果吊桥落下时旋转过快,则应该把惯性张量沿旋转轴的对应分量加大,或者直接增大 Angular Damping。

Center Of Mass Offset 允许把重心从几何中心移开。城门轴心在实际铰链位置时,门扇的重心会偏向门板中心,这样门被撞开后会自然向外摆动,而不是像被钉死在中心一样原地旋转。

2.4 锁定自由度

Rigid Body 的 Constraints 区域可以单独锁定平移和旋转自由度。这个功能常被人忽略,其实它非常有用。攻城 demo 的地面石板不需要翻滚,就把 Rotation X/Y/Z 全锁,只保留 XYZ 的平移,但平移又被地面法向约束限制;掉落的箭矢希望保持姿态稳定,就把 Angular Damping 加大并锁定部分旋转轴。锁定自由度本质上是在单个刚体上加上了内部的硬约束,减少了后续 Physics Constraint 的计算量。

三、Physics Constraint Actor 与 Component

3.1 两种挂载方式

UE5.8 提供两种入口:Physics Constraint Actor 是关卡中的独立 Actor,Physics Constraint Component 则挂在某个 Blueprint 里。老赵的城门和吊桥用了 Component,因为需要跟着父级 Blueprint 一起被生成和销毁;而一些临时性的绳索和绊索用了 Actor,方便在编辑器里直接拖拽位置。

Physics Constraint 的本质是把两个刚体的相对位置和相对旋转限制在某一范围内。它并不直接连接网格,而是连接两个 Body Instance 的约束锚点(Constraint Frame)。每个约束有两个 Frame:Constraint Actor 1 的 Frame 1 和 Constraint Actor 2 的 Frame 2。在模拟开始时,这两个 Frame 会被视为重合。

3.2 约束的工作流程

老赵把一扇城门做成两个 Static Mesh:门框和门板。门框 Simulate Physics 取消勾选,只作为静态碰撞体;门板勾选 Simulate Physics。然后在门板 Blueprint 里加一个 Physics Constraint Component,Constraint Actor 1 设为门板自己,Constraint Actor 2 设为场景里的门框 Static Mesh Actor。

在 Details > Constraint 中把 Swing 1 Motion 设为 Limited,Swing 2 Motion 设为 Locked,Twist Motion 设为 Locked。这样门板只能绕着 Swing 1 轴摆动,也就是绕着门铰链开合。如果门框和门板的相对位置没对准,模拟开始瞬间约束会猛地拉一下,门就会抖动。正确做法是在 Component 的 Details > Preview 里打开 Show Constraint Frame,把两个 Frame 都调到铰链中心,并让 Swing 1 轴与希望旋转的轴对齐。

flowchart TD
    A[创建门框 Static Mesh Actor] --> B[创建门板 Static Mesh Actor]
    B --> C[门板开启 Simulate Physics]
    C --> D[添加 Physics Constraint Component]
    D --> E[设置 Constraint Actor 1 为门板]
    E --> F[设置 Constraint Actor 2 为门框]
    F --> G[对齐 Constraint Frame 到铰链轴]
    G --> H[限制 Swing 1 并锁定 Swing 2/Twist]
    H --> I[运行模拟查看门是否能正常开合]

3.3 约束参数速查

Physics Constraint 的 Details 面板里参数非常多,老赵把它们分成四类:

  • Actors:选择要连接的两个刚体,可以留空一个,表示与世界的固定连接。
  • Constraint Bone:如果是 Skeletal Mesh,可以绑定到骨骼名。
  • Constraint Frames:两个局部坐标系,决定约束锚点和轴向。
  • Linear Limits / Angular Limits:限制相对平移和旋转。
  • Linear Motor / Angular Motor:施加力或速度驱动。
  • Breakable:超过阈值后自动断开约束。
  • Projection / Soft Constraint:稳定性和反弹参数。

四、线性限制与角度限制

4.1 Linear Limits

攻城 demo 里有一种带滑轨的投石臂:臂杆一端套在竖直滑轨上,绞盘收绳时臂杆沿滑轨上升,松开后臂杆下滑并把石块抛出。这个滑轨就是典型的线性约束。

Linear Limits 有四种模式:

  • Free:不限制平移。
  • Limited:在 Limit 值范围内移动,超出后可以软拉回,由 Soft Constraint 参数控制。
  • Locked:完全锁定该轴的平移。
  • Custom:指定自定义限制平面。

老赵把滑轨方向设为 X 轴 Free,Y、Z 轴 Locked。这样臂杆只能沿 X 轴滑动。Soft Constraint 的 Stiffness 和 Damping 决定了滑到端点时的反弹程度。Stiffness 过小,臂杆会穿出滑轨;Damping 过小,会在端点来回震荡。

线性弹簧-阻尼模型可以近似写成:

F=k(xx0)cx˙F = -k \, (x - x_0) - c \, \dot{x}

其中 kk 是 Stiffness,cc 是 Damping,x0x_0 是目标位置。对于 Limited 约束,x0x_0 就是 Limit 边界。老赵习惯把 Stiffness 设到 10610^6 以上,Damping 设到 10310^310410^4,再根据视觉表现微调。

4.2 Angular Limits

角度限制分为 Swing 1、Swing 2 和 Twist。可以把它们理解成球铰的两个摆动轴和一个扭转轴。城门的开合对应 Swing 1,门扇上下晃动对应 Swing 2,门绕竖直轴的扭转对应 Twist。

角度限制的取值:

  • Swing 1 和 Swing 2 的 Limit 范围是 00180180 度。
  • Twist 的范围可以是 180-180180180 度,也可以设为 Symmetric 让正负范围相同。

吊桥放下时,老赵把 Swing 1 设成 9090 度,这样桥面从水平放下到竖直贴墙;同时把 Swing 2 和 Twist 锁定,防止桥左右摇晃。如果 Swing 2 也 Limited 但范围很小,吊桥放下时会略微左右摆动,更像木质结构受绳索牵引的样子。

graph LR
    A[Angular Limits] --> B[Swing 1]
    A --> C[Swing 2]
    A --> D[Twist]
    B --> E[城门开合 0° ~ 90°]
    C --> F[门板上下晃动 0° ~ 5°]
    D --> G[门绕竖直轴扭转 0° ~ 10°]

4.3 局部坐标系的朝向

很多初学者在角度限制上栽跟头,原因是 Constraint Frame 没有和实际几何轴对齐。UE5.8 里每个 Constraint Frame 的 X、Y、Z 轴分别对应 Swing 1、Swing 2、Twist。在 Component Details 里打开 Show Constraint Frame 后,可以看到红色、绿色、蓝色三条小轴。红色通常对应 Swing 1,绿色对应 Swing 2,蓝色对应 Twist。把红色轴调到门铰链的旋转轴上,剩下的轴就会自然对齐。

老赵的习惯是先在编辑器里暂停模拟,选中 Physics Constraint Component,用 Ctrl + Shift + P 调出 Transform Widget,把 Frame 拖到铰链中心,再旋转到正确朝向。调整完后点击 Copy 或直接把数值写进 Details,避免下次生成时错位。

五、马达(Motor)与驱动

5.1 线性马达与角度马达

Physical Constraint 支持 Linear Motor 和 Angular Motor,每种都有三种模式:

  • Free:无驱动力。
  • Position:把两刚体拉到目标相对位置或角度,由 Stiffness 和 Damping 控制。
  • Velocity:让两刚体以目标相对速度运动。

攻城 demo 的吊桥需要在玩家踩下绞盘后匀速放下。老赵用了 Angular Motor 的 Velocity 模式,目标速度设为 20-20 度每秒。马达会在桥身上施加力矩,克服重力和阻尼后维持匀速。停止驱动时把目标速度归零,吊桥靠 Angular Damping 和重力慢慢停住。

机械臂抓取石块的阶段用了 Position 模式。爪钳由两个刚体组成,中间用 Physics Constraint 连接,目标相对位置在张开状态(3030 厘米)与闭合状态(00 厘米)之间渐变。Kp 和 Kd 就是 Stiffness 与 Damping,如果 Kp 太大,爪钳会夹得太猛导致石块弹飞。

5.2 马达参数调参

老赵总结了一套调参顺序:

  1. 先把 Motor 关掉,确认约束本身不抖、不穿模。
  2. 打开 Velocity 模式,给一个较小目标速度,观察是否能稳定跟上。
  3. 如果出现抖动,先增大 Damping,再考虑降低 Stiffness 或增加刚体质量。
  4. 切到 Position 模式后,先让目标位置保持不变,确认静态误差接近零。
  5. 再引入动态目标位置,用 Lerp 或曲线控制,避免阶跃变化。

马达的力矩上限在 Details > Angular Motor 的 Max Force 中设置。默认是 0,表示无上限。攻城锤撞门时,门轴马达如果还开着,就会出现门被强行推开但马达拼命往回拉的拉扯感。老赵在城门被撞开前先把 Angular Motor 的目标速度降到零,再增大 Damping 让它更像生锈的门轴。

5.3 驱动与动画的衔接

机械臂抛石的过程分三段:爪钳闭合抓石、绞盘拉起臂杆、松开后臂杆回弹抛石。纯 Physics Constraint 驱动可以做到前两段,但抛石后的回弹节奏不好控制。老赵的做法是:抓石和拉起阶段完全交给马达,回弹阶段在 Blueprint 里按 Timeline 设置目标角度,模拟结束前一帧读取角速度,用来估算石块出手速度。

石块出手速度 vv 与臂杆末端角速度 ω\omega 的关系近似为:

v=ω×rv = \omega \times r

其中 rr 是臂杆末端到旋转轴的距离。这个估算值和实际模拟值通常有 5%5\%15%15\% 的偏差,因为石块本身还有惯性和空气阻力,但在 gameplay 里够用了。

六、Breakable Constraint

6.1 可破坏约束的原理

城门被撞锤反复撞击后,铰链会松动、变形,最终断裂。Physics Constraint 的 Breakable 选项可以模拟这个过程。勾选 Breakable 后,约束会在受到的线性力或角力超过阈值时自动断开。Threshold 单位为牛顿或牛顿米,取决于勾选的是 Linear Breakable 还是 Angular Breakable。

老赵给城门铰链的 Linear Break Threshold 设为 5000050000 N,Angular Break Threshold 设为 2000020000 Nm。撞锤第一次撞击力约 1500015000 N,门会剧烈晃动但不会断;连续撞击累积的应力让角力超过阈值,铰链断裂,门扇倒下。这个效果比单纯在 Blueprint 里判断血量更有趣,因为它和实际物理冲量挂钩。

6.2 断裂事件的响应

约束断开后会触发 OnConstraintBroken 委托。老赵在 Blueprint 里绑定这个事件,断裂时播放木门碎裂音效、生成粒子、把门框 Static Mesh 的 Collision Profile 从 BlockAll 改成 Overlap 几秒,让倒下的门不会卡住玩家。

sequenceDiagram
    participant Hammer as 撞锤 Rigid Body
    participant Door as 城门门板
    participant Hinge as Physics Constraint
    participant Gameplay as Gameplay 逻辑

    Hammer->>Door: 施加冲量 15000 N
    Door->>Hinge: 传递力和力矩
    Hinge->>Hinge: 检测是否超过 Break Threshold
    alt 未超过阈值
        Hinge-->>Door: 保持约束,门晃动
    else 超过阈值
        Hinge->>Door: 断开约束
        Hinge->>Gameplay: 触发 OnConstraintBroken
        Gameplay->>Gameplay: 播放音效、生成粒子、调整碰撞
    end

6.3 阈值设定的经验

Break Threshold 不能直接用现实材料强度,因为游戏里的力和质量尺度往往被夸张。老赵的方法是:先做一个测试场景,用不同质量的刚体以不同速度撞击约束,记录断裂时的冲量,再反推出适合当前手感的阈值。他通常会把 Angular Break Threshold 设得比 Linear Break Threshold 小一些,因为大多数游戏物体更容易被扭转破坏。

七、物理关节与 Ragdoll

7.1 Skeletal Mesh 的 Physics Asset

守军被击飞后的瘫倒效果需要 Ragdoll。UE5.8 的 Skeletal Mesh 通过 Physics Asset 把骨骼和物理胶囊体、球体、盒体绑定。每个骨骼对应一个 Physics Body,Body 之间用 Physics Constraint 连接。打开 Physics Asset Editor,能看到一具由胶囊体串成的人形骨架。

老赵的项目里,守军角色有 1515 个 Physics Body,从 pelvis 到 head,再到四肢。每个 Body 的质量比例按人体实际分布,pelvis 最重,手掌最轻。Physics Constraint 的朝向按解剖学关节设定:肩关节是球窝关节,允许较大的 Swing 和 Twist;肘关节只允许一个轴弯曲;膝关节 similarly 只允许一个轴屈伸。

7.2 Ragdoll 的开启与关闭

Gameplay 里通常在角色死亡或受击时调用 Set All Bodies Simulate Physics,并传入 true,把动画驱动的骨骼切到物理驱动。UE5.8 也支持 Set All Bodies Below Simulate Physics,只对某根骨骼以下的肢体启用物理,其他部分继续由动画驱动,这样更适合断肢或局部击飞。

老赵在守军受击时做了分层:普通箭矢命中腿部只把腿部切到物理,身体和手臂继续播放受击动画;重锤命中躯干才开启全身 Ragdoll。切换时注意先把角色的 Mesh Component 的 Animation Mode 从 Animation Blueprint 改成 Use Animation Asset 或 None,否则动画系统会和物理系统争夺骨骼控制权。

7.3 关节稳定性

Ragdoll 最容易出的问题是关节过度拉伸和鬼畜抖动。前者是因为 Stiffness 不够或 Body 质量差异太大,后者是因为阻尼太小或时间步长不稳定。老赵在 Physics Asset Editor 里做了几件事:

  • 给脊柱和四肢约束增大 Angular Stiffness,通常在 10510^510610^6 之间。
  • 给手指、脚趾这种小质量 Body 降低 Mass Scale,避免它们被大腿带动时产生过大惯性。
  • 勾选 Projection,让超出限制的关节在求解后强制拉回,代价是可能穿模。
  • 在 Project Settings > Physics 里把 Default Solver Iteration Count 提高到 881212,让复杂约束更稳定。
architecture-beta
    group skeleton[Skeletal Mesh 骨骼层级]
        service pelvis[Pelvis Body] in skeleton
        service spine[Spine Body] in skeleton
        service head[Head Body] in skeleton
        service arm_l[Left Arm Body] in skeleton
        service leg_l[Left Leg Body] in skeleton
    group joints[Physics Constraints]
        service c_pelvis_spine[骨盆-脊柱约束] in joints
        service c_spine_head[脊柱-头约束] in joints
        service c_spine_arm_l[脊柱-左臂约束] in joints
        service c_pelvis_leg_l[骨盆-左腿约束] in joints
    pelvis --> c_pelvis_spine
    c_pelvis_spine --> spine
    spine --> c_spine_head
    c_spine_head --> head
    spine --> c_spine_arm_l
    c_spine_arm_l --> arm_l
    pelvis --> c_pelvis_leg_l
    c_pelvis_leg_l --> leg_l

7.4 从死亡动画过渡到 Ragdoll

完全从动画切到物理有时会很突兀。UE5.8 支持 Blend Physics BodiesPhysics Blend Weight。可以在 Blueprint 里把 Blend Weight 从 11 渐变到 00,让角色一边播放死亡动画,一边逐渐增加物理影响。老赵在重锤击中躯干时使用这个技巧:前 0.30.3 秒仍是动画主导,随后物理权重快速升起,角色顺着动画姿态瘫倒,而不是突然软成一滩。

八、性能与稳定性优化

8.1 物理对象数量控制

攻城 demo 第一场测试时,城墙上滚落的石块、倒下的守军、断裂的木梁全部同时模拟,帧率从 6060 跌到 3030。物理模拟的开销大致和刚体数量、约束数量、碰撞对数量成正比。老赵做了以下减法:

  • 把远处不可交互的物体改成 Static Mesh,只保留视觉层级。
  • 石块飞出视野 33 秒后调用 Set Simulate Physics(false),让它变成静态装饰。
  • 城门断裂后,倒下的门板不再和地面持续碰撞,而是用一个简化的 Box Collision 替代原来复杂的 Convex。

8.2 约束求解的循环次数

Project Settings > Physics > Default Solver Iteration Count 默认值是 44。对简单物体够用了,但对吊桥、机械臂、Ragdoll 这种多约束链条,提高到 88 能明显减少抖动。继续提高到 1616 以上收益递减,但 CPU 开销线性上升。老赵在 demo 里设为 88,Ragdoll 单独通过 Physics Asset 的 Constraint Profile 提升到 1212

8.3 CCD 与 Sleep

高速运动的石块和小型抛射物容易穿透薄墙,这时要开启 Continuous Collision Detection,在 Details > Physics > Use CCD 勾选。CCD 会增加少量开销,但对攻城锤、箭矢、抛石这些高速物体是必要的。

另一方面,静止物体应该尽快进入 Sleep 状态。Sleep Threshold 控制速度和角速度低于多少时物体停止主动模拟。老赵把地面石块堆的 Sleep Threshold 稍微提高,等它们落稳后就不再消耗 CPU。

8.4 固定时间步长

Physical simulation 对时间步长敏感。UE5.8 默认使用可变时间步长,在帧率波动时约束容易爆炸。可以在 Project Settings > Physics > Substepping 里开启固定子步长。Max Substep Delta Time 设为 0.01660.0166 秒,Max Substeps 设为 66。这样即使主循环掉到 3030 FPS,物理仍以最高 6060 Hz 更新。代价是掉帧时物理会吃掉更多 CPU。

8.5 异步物理

UE5.8 支持 Async Physics Tick,把物理模拟放到独立线程,和渲染线程并行。开启后延迟会增加一帧左右,但对帧率平滑很有帮助。老赵在 demo 里开了 Async Physics,配合固定子步长使用。注意:如果 gameplay 逻辑每帧都读取刚体位置和速度,异步物理会带来一帧的延迟感,需要做插值补偿。

九、常见物理关节问题

9.1 约束一开始模拟就疯狂抖动

最常见的原因是 Constraint Frame 没对齐。模拟第一帧,两个 Frame 被强制重合,如果初始姿态下它们偏离太远,物理引擎会施加巨大冲量把它们拉到一起。解决方法是进入编辑器暂停状态,精确调整 Frame 的位置和旋转,或在 BeginPlay 时通过 Blueprint 用 Set Constraint Reference Frame 重新对齐。

另一个原因是质量和惯性差异过大。一块 0.10.1 kg 的小木板挂到 10001000 kg 的门框上,约束求解会不稳定。解决方法是给轻物体增加 Mass Scale,或者降低重物体的质量,让两侧差距不超过两个数量级。

9.2 约束断裂位置不对

Breakable Constraint 断开后,被约束的两个物体可能突然弹开。这是因为约束消失前积累的弹性能量一次性释放。老赵在断裂事件里给两个刚体都施加一个和当前速度方向相反的冲量,模拟铰链断裂时的摩擦和变形吸能。冲量大小按断裂前一刻的相对速度估算,公式近似为:

Δp=αmeffΔv\Delta \mathbf{p} = -\alpha \, m_{\text{eff}} \, \Delta \mathbf{v}

其中 meffm_{\text{eff}} 是两侧质量的有效值,α\alpha 是吸能系数,通常取 0.30.30.70.7

9.3 Ragdoll 肢体穿插进躯干

这是 Skeletal Mesh 的 Collision 太简单造成的。胶囊体和球体无法精确贴合肌肉轮廓,手臂倒下时容易插进胸口。老赵的解决方案是:给躯干加一层稍大的 Collision,让四肢 Body 在靠近躯干时被推开;同时给肩关节和髋关节加上 Contact Distance 和 Restitution,让它们在极限位置有柔和反弹。

9.4 马达停不下来或反向抖动

Velocity 模式下的马达如果目标速度和当前速度方向相反,会出现来回拉锯。例如吊桥已经接近水平,马达仍试图继续下放。老赵在 Blueprint 里监测当前角度,当接近 Limit 边界时把目标速度线性降到零,并切换到 Position 模式把桥锁在最终位置。不要让 Velocity 马达一直开到头。

9.5 物理和动画互相抢骨骼

Skeletal Mesh 的 Animation Mode 和 Physics 驱动是互斥的。如果一边播动画一边开 Simulate Physics,同一根骨骼会被两个系统同时写入,导致撕裂。UE5.8 的处理方式是:当 Physics Blend Weight 为 11 时完全由物理驱动,为 00 时完全由动画驱动。中间值做混合。切换前务必把权重设到一端,再启用或关闭物理。

十、把四个场景串起来

老赵最后把城门、吊桥、守军 Ragdoll 和机械臂四个模块串成了一个攻城流程:

  1. 玩家操控撞锤撞击城门,Physics Constraint 在累积应力下断裂,门板倒下。
  2. 城门破开后,另一组玩家启动绞盘,Angular Motor 以 Velocity 模式匀速放下吊桥。
  3. 守军被箭矢和重锤击中,按命中部位分层切换到 Ragdoll,尸体沿台阶滚落。
  4. 城墙上的机械臂用 Position 马达抓石、用 Velocity 马达起臂,最后松手抛石。

整个 demo 没有写复杂的动画蓝图,也没有用关键帧控制物体运动,所有交互都靠 Rigid Body 和 Physics Constraint 驱动。物理引擎的优势就在这里:它把力和几何关系交给系统计算,设计师只需要设定材料参数和约束条件。

十一、代码示例:在 C++ 中创建一个可破坏铰链

下面这段代码展示了如何在 C++ 里创建两个 Static Mesh Actor,并在它们之间添加一个可破坏的 Physics Constraint。代码很短,只用来示范关键 API。

#include "PhysicsEngine/PhysicsConstraintActor.h"
#include "PhysicsEngine/PhysicsConstraintComponent.h"

void AMyGameMode::CreateBreakableHinge(
    AStaticMeshActor* DoorFrame,
    AStaticMeshActor* DoorPanel)
{
    FActorSpawnParameters Params;
    Params.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;

    APhysicsConstraintActor* Constraint = GetWorld()->SpawnActor<APhysicsConstraintActor>(
        APhysicsConstraintActor::StaticClass(),
        DoorFrame->GetActorLocation(),
        DoorFrame->GetActorRotation(),
        Params);

    UPhysicsConstraintComponent* Comp = Constraint->GetConstraintComponent();
    Comp->SetConstrainedComponents(
        DoorPanel->GetStaticMeshComponent(), NAME_None,
        DoorFrame->GetStaticMeshComponent(), NAME_None);

    Comp->SetAngularSwing1Limit(EAngularConstraintMotion::ACM_Limited, 90.0f);
    Comp->SetAngularSwing2Limit(EAngularConstraintMotion::ACM_Locked, 0.0f);
    Comp->SetAngularTwistLimit(EAngularConstraintMotion::ACM_Locked, 0.0f);

    Comp->SetLinearXLimit(ELinearConstraintMotion::LCM_Locked, 0.0f);
    Comp->SetLinearYLimit(ELinearConstraintMotion::LCM_Locked, 0.0f);
    Comp->SetLinearZLimit(ELinearConstraintMotion::LCM_Locked, 0.0f);

    Comp->SetBreakable(true, true);
    Comp->SetLinearBreakThreshold(50000.0f);
    Comp->SetAngularBreakThreshold(20000.0f);

    Comp->OnConstraintBroken.AddDynamic(this, &AMyGameMode::OnHingeBroken);
}

void AMyGameMode::OnHingeBroken()
{
    // 播放音效、生成粒子、调整碰撞响应
}

十二、总结

Rigid Body 和 Physics Constraint 是 UE5.8 物理系统的两条主线:前者让物体具备质量、惯性和碰撞响应,后者把多个物体按规则连接起来。从城门铰链到吊桥绞盘,从布娃娃尸体到投石机械臂,这些看似不同的效果本质上都遵循同一套力学模型。

实际工作中,问题的根源往往不在参数本身,而在坐标系对齐、质量比例、自由度锁定和马达模式选择这几个基础环节。把它们理顺之后,剩下的就是根据场景手感微调 Stiffness、Damping 和 Break Threshold。物理模拟不是玄学,只是需要把现实世界里的力、约束和材料属性翻译成引擎里的数值。