前两代的破坏系统在 UE5 里被统一到 Chaos Destruction:资产侧是 GeometryCollection(几何体集合),运行侧是刚体簇(Cluster)+ 字段系统(Field)的断裂判定。上手不难——Fracture 插件一键碎个盒子——但"为什么这一锤下去只掉了一层皮而那一锤塌了半面墙",需要理解簇层级和损伤传播这两条主线。
资产:GeometryCollection 的数据布局
GeometryCollection 是独立的资产类型(.uasset,GeometryCollection UCLASS),内部核心是:
- 一组变换空间(Transform 数组):每个几何簇一个节点,节点存局部变换 + 父索引,构成树;
- 一组共享网格:叶子节点持有对几何数据的引用(顶点/索引/材质组),父簇不持几何,只持"我是哪几个叶子的并集"这个逻辑关系;
- 碰撞表示:每个叶子生成对应的
FImplicitObject(凸包或三角网格近似)。
树是分形破碎的直接结果。Fracture 插件对一块墙做 Voronoi 碎裂时,生成的不只是碎片列表,而是多级簇:若干小碎片聚成一个中级簇,若干中级簇再聚成"整面墙"。层级深度和每级簇大小由破碎参数控制。运行时的关键性质:任何一个内部节点被激活为刚体时,它的子树默认处于"胶着"状态——表现为一个整体刚体,而不是一堆独立碎片。
运行时:簇状态机
每个簇节点在求解器里是一个刚体粒子,存在三种状态:
- Dynamic:正常参与仿真的独立刚体;
- Sleeping / Clustered(胶着):作为父簇的一部分,跟随父簇的变换,自身不耗求解预算;
- Disabled(剔除):被 Set 成不模拟(
Set Anchored一族),完全静态,连 broad phase 都不进。
断裂的语义就是把一个父簇解胶:父簇刚体消失,子簇(或叶子)从胶着态翻成 Dynamic,各自带父簇的速度入场。翻的过程产生一组新粒子、新约束(子之间的接触约束)、新岛——岛管理篇的 union/find 在这里高频发生,一场爆炸一帧可能拆出几百个新岛。
"什么时候解胶"由字段系统驱动,这是 Destruction 和外部世界交互的唯一入口。
字段(Field):断裂判定的通用协议
字段是一个空间函数:给定世界坐标,返回标量或向量。FMathField 系实现(球体衰减场、径向冲击场、平面场等)。Gameplay 侧调用 UGeometryCollectionComponent::ApplyField 一族接口,传入场定义 + 操作类型(EFieldCommandType),求解器在字段评估 pass 里对每个簇节点采样:
- 采样值超过节点的断裂阈值(
DamageThreshold,每级簇可不同)→ 标记该节点断裂; - 带速度的场(RadialFalloff + 冲量)同时给节点注入线速度/角速度。
损伤传播是阈值的层级瀑布:一次锤子打击,场在命中点的采样值最大,逐级衰减。表层小簇先超阈值断裂,释放出的子簇继承速度散开;如果场强足够深,第二级簇也被直接判裂。墙皮被敲掉一层而墙体还在,就是场衰减只够到第一级;"半面墙塌了"是锤击点附近的第二级簇成片断裂。调 Destruction 手感,本质是在调这棵树每级的 DamageThreshold 和场的衰减速率。
数学上值得记一句:场对簇的判定是纯标量比较,没有任何断裂力学(没有应力张量、没有裂纹扩展模拟)。物理可信感靠层级和阈值曲线拟合出来,不是算出来的。这是性能和效果之间的诚实取舍——真做裂纹扩展,一堵墙的碎裂就够一个核跑几秒。
性能与内存的账
簇机制最大的收益是休眠粒度对齐了视觉粒度:一堵完整的墙是一个(或几个)胶着刚体,静态休眠,物理开销趋近于零。破碎瞬间是开销峰值——新刚体注册、碰撞对生成、岛重建同帧发生。爆炸碎片雨场景要把 MaxClusterLevel 和单次断裂数量管住,必要时用 Removal(直接删除簇而不生成碎片刚体,配合预烘焙碎片特效)替代 Dynamic 碎裂。
内存侧的坑:GeometryCollection 的每个叶子都有一份碰撞表示,簇层级越深,碰撞数据越接近原始几何的倍数。.uasset 里看到 GeometryCollection 体积爆炸,多半是多级破碎 × 三角网格碰撞(per-fragment tri mesh)的组合,把叶子碰撞换成凸包近似(Fracture 面板 Convex 选项)通常能砍一半。
源码入口
- 组件入口:
GeometryCollectionEngine模块的UGeometryCollectionComponent,ApplyPhysicsField/ApplyKinematicField是字段注入的两个 UFUNCTION; - 求解器桥:
GeometryCollectionPhysicsProxy(GeometryCollection模块),负责把组件的字段命令翻译成求解器 pass,把簇状态机接进 FPBDRigidsSolver; - 断裂执行:
Chaos/GeometryCollection/下的FGeometryCollectionPhysicsProxy::UpdateCallback,看断裂标记怎么转成"翻状态 + 建约束"; - 字段评估:
Field/ChaosField.h的FPerlinField/FRadialFalloff实现,注意评估在物理线程跑,字段采样 cost 直接进物理帧时间。
簇层级和断裂路径的示意: