前言
早在虚幻5更新之后,Chaos物理成为了主要的物理解算系统,这个系统有着出色的可破坏场景表现和高保真的布料模拟。在虚幻5.4中,Chaos物理系统有了比较大的改变与更新。这次分享将会为大家带来一些使用Chaos物理相关功能的知识与技巧,帮助大家更熟练运用Chaos物理,并且兼备质量与性能。
本文出自https://www.youtube.com/watch?v=uCYGFdEWyZw,讲者是Benn Gallagher。
正文
一、大规模的多人在线物理表现
大家应该听说过《堡垒之夜》的乐高模式,或许还有小伙伴游玩过这个模式。乐高模式允许玩家在一个开放世界关卡中自由地创建、摧毁和移动各种各样的物理对象,并且还能保证游戏性能和网络表现都很流畅。
1.1 遇到的挑战
为了完成这些,Epic也是遇到了许多挑战:
首先是一套完整的资产创建流程,因为乐高由很多的小块组成,我们需要使用数据流定义一个乐高建筑资产,包含各种可破坏性碎块相关的数据,并且还要定义它的网格体集合等等资产数据。
然后是建筑与建筑、建筑与世界之间的连接性,并且连在一起的建筑还得有对应的物理交互。
因此整个游戏模式的规模就大起来了,这样我们就不得不要考虑这些物理计算在其他平台上的表现如何,在性能优化上重点下功夫。
最后也是比较重要的一点就是网络,我们需要将这么多物理模拟的东西同步给所有玩家,并且还要保证流畅性,避免物理矫正给玩家带来卡顿感。
1.2 资产工作流
用过Chaos破坏的开发者对于Geometry Collection应该很熟悉,它是用来定义一个对象被破坏时产生的网格体碎片的,并且我们可以自定义碎块的大致形状。
而我们要面临的挑战就是,将一大堆这样的资产分成几何集合,然后还具有可控且非破坏性的特点。为此我们在数据流的基础上新建了一个管线,它基于节点并且允许我们模块化生成碎块的流程。也就是说我们可以定义一个生成碎块的流程,然后直接将大量的网格体资产丢进管线中自动处理。需要注意的是处理几何集合的数据流工具在虚幻5.4还是实验性功能,未来会对此进行更多的更新。
1.3 建筑的连接性
当我们有了大量的建筑对象之后,我们还得处理这些建筑的相互连接性。为此我们开发了一个连接图组件和系统来管理这些建筑对象之间的连接关系。为了能够让每个玩家都能得到同样的结果,我们只允许网络权威方处理连接关系,这样就只有服务器在处理这些连接关系。这个系统还会快速检查各个建筑的连接关系,并且检查建筑是否接地,如果不接地就会转为物理模拟。
上述我们聊的连接图只是一个Gameplay系统,接下来我们要开始处理物理系统中的事情了。为了将这些分散的网格体连接起来,我们开发了一个Cluster Union(簇集合)的组件,它可以将分散的网格体连接在一起成为物理场景中新的物理对象。连接图会帮我们决定哪些网格体会成为一个簇。并且簇集合还能在被破坏的时候,重新计算哪些网格体会连在一起成为一个簇,比如我们将下图中的建筑对半砍开,他就会自动分成两个簇对象进行物理模拟。
如果有小伙伴了解过的话,它其实代替了之前引擎版本中的Cluster Group(簇组合)。这个旧的Cluster Group可以在编辑的时候快速分簇,但是在运行时还没有一个简单且快速的方法动态分组。
1.4 运算消耗
像这样可以动态分簇的物体,就不能够只是简单的把碰撞也连接在一起了,我们需要将连接在一起的碰撞简化,当成单独一个形体来模拟。并且这个形状只会用来模拟物理,而角色还是能够站在上面,查询这个形体的具体碰撞的。下图是我们使用这个简化算法的过程,一开始有很多盒体碰撞,到后来逐渐减少,并且这个简化程度是可以通过参数控制的。为了防止最后简化程度太高,导致看上去的碰撞和实际碰撞不一致,我们一般调整参数到左下角那种情况就不会继续简化了。
上面我们尝试解决了模拟计算的问题,接下来我们就需要解决渲染的问题了。按照正常来讲,Geometry Collections会被一个个地单独渲染,一个块一个Proxy,因为每一片碎块的形状是独一无二的。但是在乐高模式中,乐高碎块有很高的重复度,所以我们就可以构建一个ISM池去管理这些相同形状的碎块,并且让Geometry Collections可以拿到这些碎块的渲染地址,然后在破碎之后渲染出来。在处理完碎片之后,我们发现在世界构建中也可以使用实例化网格体来处理这些相同结构的建筑,这样就可以大大加快场景的渲染速度了。如下图,我们有这四种形状的碎块,我们根据碎块种类构建ISM池,然后就会有两个Geometry Collections组件绑定在方块形状和球体形状上。
在建筑破坏后产生的碎块是没有根的Geometry Collection粒子,它们不会和任何簇相连。这个碎块不会影响游戏玩法,不对其他物体施加力,但能接收力,比如玩家或者其他物体撞这些粒子,它们会动,而它去撞其他碰撞则会被弹开。所以这些碎块粒子都是视觉效果,只会在客户端上进行计算,过一会儿就会消失。
乐高模式的地图中有湖泊、河流、海洋等水体,所以我们还得处理这些碎块的浮力表现。这个浮力系统需要适应各种情况,需要流畅地运行,并且由于项目是异步物理的,所以浮力系统需要在物理线程中处理。我们首先会像上面简化物理碰撞那样,将物体的大致体积找出来,然后获得物体在水中的体积,再通过质心为物体施加计算好的浮力。然后我们还会根据水体的参数增加附加的力,比如根据河流流速给物体施加流速的力。这个系统在虚幻5.4中可用,插件名叫Buoyancy,任何物理场景中的刚体都能体现出浮力。乐高模式中的簇可以看做一个刚体网格体,碎块粒子也可以看做是一个刚体网格体,所以都能被浮力所影响。
1.5 网络同步
上面我们提到,服务器会处理连接破坏事件,但模拟还得让客户端处理。这样的话就会出现一种情况,假如客户端的网络延迟很高,可破坏对象会被弹开,然后莫名其妙地碎掉,因为客户端“错过”了服务器发给它的破坏事件。为了修复这个问题也挺困难的,服务器上不会模拟破坏后的碎块,所以对于破坏事件的预测和回滚显然是不现实的。并且我们不可能预测破坏事件,因为有时候预测事件是错误的,到头来还得回滚然后重新模拟。为此我们使用了预测插值,让客户端的物理同步稍微滞后于服务器,滞后约半个网络来回时间,这样就能保证服务器发送的破坏事件能够让客户端准确接收到。
预测插值是这么工作的,首先我们会算出当前客户端模拟的状态和服务器当前的状态的位置差值,然后差值除以网络来回时间,这就是一个靠近服务器实际位置的速度。在第三步,我们会算出当前速度与服务器速度的差异,然后将这个速度差异与匹配速度(靠近服务器实际位置的速度)相加,得到一个最终矫正速度,这个速度可以严格匹配上服务器的速度。我们不能就这样直接使用这个速度,我们得根据时间膨胀缩放这个速度,然后再应用到我们的客户端物体上。这种预测插值可以有效避免网络矫正带来的瞬移现象(除非客户端的网络真的太卡了,才会有瞬移现象出现)。这里只演示了矫正位置与速度的计算,而对于旋转与角速度也是进行了同样的计算。
二、高保真的布料模拟
为了让MetaHuman中的服装布料模拟更高保真更用户可控,我们根据以下目标开发了相对应的组件与工具:
1.让布料模拟不再依赖于骨骼网格体,不再依赖于骨骼网格体组件的Proxy,将布料模拟分离出来,并且通过一个模拟网格体控制多个渲染部分。
2.布料模拟可以通过数据流工具与自动化工具更加可塑,自动生成布料配置、布料LOD以及蒙皮选项。
3.丰富当前布料编辑的工具,使其成为一个独立的布料资产编辑器。
2.1 布料资产编辑器
下面是布料编辑工具的示例图。下方是数据流,中间是3D视图区域与绘图区域。
并且我们可以通过给骨骼网格体设置动画,实时预览布料模拟的结果。
下面是数据流图表。这个数据流图表可以帮助我们处理一下导入进来的原始数据,比如这个图中导入了服装的静态网格体,它没有蒙皮数据,所以我们需要先给这个服装生成蒙皮数据。方法很多,或是根据骨骼网格体自动生成,或是根据顶点绘制等等。然后我们根据这三个权重图配置布料模拟的相关数据,包括最大距离,逆止,弯曲等等,并且这些设置布料参数的节点都有在数据流图表中暴露出来。最终我们会为这个布料设置物理资产,然后输出给布料资产终端,接下来就可以进行编辑器内的工作了。在虚幻社区中已经有很多关于布料资产以及数据流图表的教程,感兴趣的小伙伴可以自行查阅。
2.2 布料制作工作流程
除了静态网格体,骨骼网格体外,我们还支持USD格式的文件,也就是Marvelous Designer中的布料文件。虚幻5.4中可以启用USD导入管线插件,该插件目前还处于Beta阶段。
整体的布料制作流程更端对端。首先在Marvelous Designer中做好衣服的布料,然后通过静态网格体、骨骼网格体或者USD格式文件将其导入。然后在布料资产编辑器中创建数据流,为布料添加参数。最后就可以将资产迁移到UEFN项目中,使用Cloth Component添加到我们的角色Actor上。需要注意的是,如果Cloth Component的父组件是角色的骨骼网格体,布料就会和之前的布料系统一样跟着角色骨架形变。如果导入的是静态网格体,就需要在数据流中生成蒙皮数据才能受角色骨架形变。
这个示例中的人物衣服是完全布料模拟的,我们可以使用数据流自动生成布料的LOD,在高细节LOD情况下可以到达30帧,如果在使用低细节LOD的情况下可以达到40~60帧以上。我们可以根据不同平台或者不同帧率目标需求调整布料的相关参数,LOD、迭代次数等,平衡布料的性能与视觉表现。
我们可以通过Remesh节点来帮助我们自动生成各种LOD,并且还可以分别调整模拟网格体的顶点数和渲染网格体的顶点数。
以上就是我们现在制作衣服布料的新工作流,可以看到数据流非常强大,让我们更易导入布料,编辑更具非破坏性,布料参数更易配置等等。并且未来还会继续优化流程,简化布料制作工作流,让精力更多地投入到创作中。现在社区论坛有很多布料制作相关的文档与教程,感兴趣的小伙伴可以前去查阅与研究。
三、Chaos Visual Debugger(CVD)
3.1 CVD介绍
我们可以在“工具→调试→Chaos可视调试器”打开这个工具,这个工具实际上是另外一个虚幻引擎实例,并且隶属于Trace系统。这个Trace系统其实就是Unreal Insight所使用的系统。就像使用Unreal Insight录制性能追踪一样,我们可以使用这个CVD工具录制物理状态,然后在另一个虚幻引擎实例回放这些物理状态。
就像在Insight里看到一帧内发生了什么事件一样,在CVD中也能看到物理解算器在不同阶段的物理计算中发生了什么。需要注意的是,以下我会称Chaos中的Particle称为物理对象,方便大家理解。
Begin阶段就是我们在应用任何参数之前的阶段;
接着我们进入Integrate阶段,这时候我们会将物理场景中的所有带物理的对象根据速度将其移动,它们在这一阶段可能会交叉在一起;
接着在Broad阶段我们就会开始进行碰撞检测,根据碰撞框计算出哪些对象重叠;
然后Narrow阶段就是准确获取哪些例子碰撞了、怎么碰撞的等数据,建立一个接触数据集来描述碰撞;
在Pre Solve阶段这些物理对象应该处理好了各种约束和碰撞的数据了,但还没应用;
而在Post Solve阶段,我们就已经应用上所有的约束与碰撞的结果了;
End阶段会根据情况进行额外计算,比如重新模拟功能、后检测碰撞功能等。
在我们录制好一段回放后,读取这个回放,我们可以通过这些设置来显示一些需要Debug的物理功能,并且这些Debug功能会随未来更新慢慢变多。
3.2 演示案例
这里我们录制了一段Lyra的游玩片段,不过在加载这个回放之前我们先看看这个界面长什么样。看着挺眼熟对不对,右边是大纲,中间是主要视图,下面是解算器的时间线,这个时间线还会有各种解算器单独的轨道,比如客户端自己计算的,服务器计算的等等。
然后我们看到这个场景,当我们打开可视化效果之后,我们会看到各种颜色的碰撞对象。静态网格体是绿色的,运动学对象是蓝色的,如果物体进入了休眠状态,就会显示为黄色或者红色。除了这种可视化效果外,我们还可以通过颜色区分各种物理形体,球体、胶囊体、盒体等。当我们把服务端回放和客户端回放一起加载,还可以根据颜色进行区分,更方便看出差异。
当游戏开始的时候,我们可以看到一些玩家从出生点跑了出来。
当有一个玩家死亡时,角色会进入布娃娃状态,让我们现在好好看看这个布娃娃。当我们选中这个布娃娃的某个形体时,我们就能在右边的碰撞数据细节面板中看到实时的碰撞信息。
这里有着碰撞计算的所有信息,包括两个碰撞对象是什么、是否启用CCD、物理材质是什么、碰撞推力是多少等等数据。并且希望大家可以通过这些显示出来的参数开始诊断自己游戏项目中的碰撞与物理问题。
然后我们也可以看看角色的胶囊体,实际上在写角色移动的时候,使用了很多扫描函数来检查角色的运动学移动。向前走我们需要向前检查空间是否能够移动,进入掉落状态我们需要检查当前我们脚下的碰撞是否可以站立等等。除此之外,动画系统也会向下检测地板,用来进行IK调整。
下图是未开启查询显示的视图。
而这是开启了查询显示的视图。
当我们选中了某一个查询,比如射线检测、Sweep等,会显示出更多参数。谁是阻碍查询的对象、为什么被阻碍了、还检查了哪些对象等等参数。如果您的项目中出现了,一个查询行为检测到了一个不该检测到的球体或者其他对象,可以使用CVD帮助您快速诊断出问题。
以上只是对CVD的简单介绍,并且希望大家在得知了这个工具之后,能利用这个工具诊断自己项目中出现的物理与碰撞问题。如果大家需要更深入地了解,强烈推荐大家阅读一下下面这篇文章:https://dev.epicgames.com/community/learning/tutorials/EpnO/unreal-engine-chaos-visual-debugger-user-guide。这篇文章几乎涵盖了CVD的所有功能,包括介绍与使用方法等。
四、优化Chaos
优化一个系统最常规的东西莫过于优化CPU性能或者内存性能,首先我们看到物理对象的内存占用部分。一个物理对象以SoA格式数组结构储存着,SoA格式是一种面向数据的容器,这样是为了让数据能够不断更新。这种格式是By Access模式,这个模式可以为粒子集成等算法提供一些CPU缓存优势。粒子集成将会历遍所有物理对象,更新他们的位置与速度等数据,但不会处理几何形状或者摩擦力等因素。
下图是物理对象所储存的数据。天蓝色是四元数,紫蓝色是向量,粉色是浮点。使用这种储存方式可以为物理场景中的每一个物理对象节省了大约144字节。在5.4中保存物理数据,就会以一种更窄的宽度储存各种物理参数。
接着就是Geometry Collection的内存问题。GC相对来说更加复杂,它需要将碎块的几何结构与物理参数储存在一起,并且还需要压缩资产的大小以及运行时的内存占用。为了在运行时降低GC的内存占用,我们可以在真正需要破碎的时候加载这些到内存中,但是我们的游戏体验就有较为明显的卡顿,这需要在CPU与内存之间进行衡量。
当破碎发生的时候,这些破碎的物理对象需要动态地组合在一起,这样才能优化整体的物理计算与内存占用。还有就是当玩家进行爆炸行为时,周围的物体就会被大量破碎,这时候我们就会限制同时处理破碎事件的次数,当单次更新中需要破碎的次数大于限制值,这些未处理的破碎会留到之后的帧中处理。
p.Chaos.Clustering.PerAdvanceBreaksAllowed和p.Chaos.Clustering.PerAdvanceBreaksRescheduleLimit两个CVar可以控制同时处理破碎事件的次数以及破碎事件滞留到未来帧的次数。如果这些本该破碎的物理对象因限制参数没有破碎,就需要在下一次玩家行为或者物理影响下,达到破碎条件并且不被限制的情况下才会破碎。我们可以根据自己游戏项目的破碎量衡量这两个参数,来保证我们的物理线程能够流畅更新。
截至虚幻5.4,Chaos物理对象的几何形体是独一无二且不可变的,如果想要修改形体,就需要修改这个物理对象的形状就必须同时修改其层级结构。而在未来的版本中,这些物理对象的几何结构将不再是唯一的指针,我们可以更方便地修改这些几何结构,并且可以共享生命周期。当我们在进行类似于组合或者焊接几何结构的行为时,这样会快很多,特别是我们有一个很大的几何结构集合体的时候。在静态网格体中,我们只有简单或者复杂碰撞,而在Geometry Collection中会有成百上千个碎块,这种改进就显得尤为重要。
在虚幻5.4之前,这些物理反馈事件会逐Actor分发,这样会造成巨大的消耗。而在虚幻5.4,我们引入了一个叫做Chaos Event Relay的东西帮助我们将这些事件聚合在一起,用户可以自己过滤掉不需要用到的事件。比如我们可以将碰撞事件集中处理,让用户过滤掉一些事件,之后正常触发一些音频播放。当然这个方案只能适用于某些场景,如果我们真的需要让一个Actor在被命中时有反馈,还是需要将命中事件分发给这些Actor。这两个方案可以混合使用。
结语
本次分享由浅入深,从乐高模式开始讲起,到布料资产的制作,然后就是Chaos Visual Debugger,最后讲到Chaos优化。从头到尾都是干货,并且推荐大家细嚼慢咽,细细品味后一定能收获良多。最后祝大家创作愉快,工作顺利!
全文完
做动画总穿模?检查自动修正插件来了
很好,看完以后这个冬天更冷了【胆小慎入】