背景
最近要做爆破仿真,所以开始带薪学习 Chaos 破碎系统(欸嘿)。总体而言感觉目前 Chaos 还是一个不怎么完善的系统,很多功能都很难以使用,尤其是如果想在运行状态下对一些参数进行动态修改。感觉每次尝试都心惊肉跳,生怕它出现什么理论上不该出现的现象。
我们的需求是希望爆破体可以动态添加,完成一次爆破以后,在不重置整个场景的基础上重置这个破碎体,需要的时候可以进行再次爆破。但在 5.0 中并没有破碎体重置的函数,也没找到各种动态设置的能力,因此也只能看看源码中是否有相关解法了。不过总体而已跌跌撞撞还是大概搞明白了一些东西,也是我第一次必须从 UE 源码中找问题的答案。这个解法未必是最合适甚至未必是完全正确的,只是目前测试下来可以使用的一种解法。总之就是如果后续有碰到这种需求,也可以给做个参考叭。
关于怎么创建破碎体、怎么爆破等等,网上已经有非常非常非常多的教程了,所以这里不再赘述。总之就是基于 Static Mesh 创建 GeometryCollision,将 GeometryCollision 放置在场景中,再使用 master field 爆破。当所有东西都预制在场景里时,整个流程十分顺滑,但当我们希望所有东西都动态添加时,就不是那么回事了。
Geometry Collection
Geometry Collection 是几何体的集合,基本就可以被看做预制好的破碎体。当我们把 Geometry Collection 放入场景中时,场景中会生成一个 Geometry Collection Actor,这个 actor 内含一个 Geometry Collection Component,绝大部分破碎体的参数都是直接属于这个 Component 的。
Rest Collision 是 Geometry Collection Compoenet的核心参数,它的类型就是之前创建的 Geometry Collection。设置了 Rest Collision 以后,所有的相关参数(如材质、破碎阈值等)都会自动设为该 Geometry Collection 的默认参数。

动态添加
所以动态添加的核心就是动态设置 RestCollision。UE 5.2 直接在蓝图中提供了 SetRestCollision()
方法,5.0 的 C++ 中也有相应的 public 函数,并都内置了同步更新其他相关参数的功能。但是当我们创建一个新的 Geometry Collection Actor 并直接执行了它包含的 Geometry Collection Compoenet 的这个方法以后,虽然在细节面板上可以看到 rest collision 和相关参数已经全部设置完全了,但是场景中渲染效果却没有任何变化。
如果我们只需要动态创建指定破碎体,那我们只需要使用 AddGeometryCollectionComponent
节点在 Actor 中添加一个新的 Geometry Collection Component,并在写蓝图时在 details 里手动设置好 Rest Collection 的参数即可。但当我们有多种破碎体时,每个破碎体都需要自己的 AddGeometryCollectionComponent
节点,逻辑无法复用。
所以如果想 runtime 动态指定破碎体的类型,除了rest collection,还有两个重要函数,ResetDynamicCollection()
和 RecreatePhysicsState()
。ResetDynamicCollection()
是属于 GeometryCollectionComponent 的 protected 的函数,作用是重置渲染效果。执行完这个函数后,破碎体 level 0 的渲染效果已经出现了,但没有任何物理效果,也没法被力场爆破。因此我们还需要一个属于 UActorComponent 的 public 函数 RecreatePhysicsState()
来重置破碎体的物理效果。鉴于包括了非 public 函数,如果不想修改引擎,我们就只能建立一个继承 GeometryCollectionComponent 类的 MyGeometryCollectionComponent 类来实现这个功能。代码如下
1 | UCLASS() |
动态修改
虽然这个方法实现了动态添加,但只少在5.0 和 5.2 版本,爆破后或者第二次设置 rest collision 后, ResetDynamicCollection()
就失效了,场景效果完全没有变化。因此如果想在爆破后重新变成未爆破的情况,目前只找到了删除再添加一个办法。
此外,当一个破碎体被放置在场景中并设置好相关参数后,动态修改也是漏洞百出。比如修改 GeometryCollectionActor 的 location 只会修改 level 0 的渲染效果,如果在没爆破的时候修改,虽然视觉上 location 改变了,但其实破碎块的位置和力的触发效果并没有随之改变,在新坐标上添加爆破力不会有任何反应,而在原坐标上添加爆破力则使新坐标上的 mesh 消失,原坐标上出现爆破的效果。如果已经爆破,会在目标位置出现一次闪烁,但破碎了的部分并不会变化。
总结
总体而言, Chaos 破碎系统还是一个不怎么完善的功能。当然考虑到动态设置其实并不算一个大众的需求,且破碎体本身就是一个复杂且庞大的功能,只能说 UE 尽力了.jpg。