集成性能
性能
Crushform 的开销来自几个参数:图集及其槽位、每个晶格的分辨率、插件重建碰撞和污垢的频率,以及可同时运行的轮胎、碎片和声音的数量。本页列出每个参数及其默认值。本页不给出帧时间,因为它取决于你的项目。请使用本页最后一节中的命令测量你自己的项目。
图集及其槽位
Section titled “图集及其槽位”每个受损车身占用图集中的一个槽位,该槽位保存其晶格。图集是 UCFSettings::Atlas 中的渲染目标。它的表面在每一边上限制为 4096 个纹素(CFTypes.h 中的 MaxAtlasSize),槽位数量为表面面积除以单个槽位的面积,即 UCFSettings::SlotWidth 乘以 UCFSettings::SlotHeight。
- 当晶格的 ResX 乘以 ResZ 不超过
SlotWidth,且 ResY 不超过SlotHeight时,晶格即可放入槽位。默认配置文件的UCFProfile::Resolution为 16 乘 8 乘 8,可放入默认的 256 乘 8 槽位。 - 槽位必须能容纳最小的晶格,即 4 乘 4 个节点。宽度小于 16 纹素或高度小于 4 纹素的槽位会使凹陷不可见,日志中会给出说明。
- 图集必须是线性的 B8G8R8A8:即 RTF_RGBA8 渲染目标,或不带 sRGB 的 BGRA8 贴图。其他任何格式同样会使凹陷不可见。
当所有槽位都被占用时,一个新的受损车身会占用距离最远的受损车身的槽位,但前提是该车身比新车身离摄像机更远。那个最远的车身随后会等待,并以未受损的状态绘制,直到有槽位空出。与最远车身距离相同的车身同样会等待。
晶格与配置文件
Section titled “晶格与配置文件”晶格是配置文件为每个车身设定的开销。
UCFProfile::Resolution(默认 16 乘 8 乘 8)是晶格的节点数。晶格越大,需要的槽位也越大,如上所述。UCFProfile::bDents(开):关闭后,撞击和挤压都不会使车身凹陷或刮擦。污垢仍然有效。UCFProfile::DirtScale(1):车身上的每一次污垢沉积都会乘以该值。为 0 时,车身完全没有污垢网格。UCFProfile::MaxPlausibleDeltaV(40 m/s):更猛烈的撞击会以此上限报告,服务器会拒绝超过该值的任何报告。
UCFSettings::MaxReportsPerSecond(60)是服务器每秒从一个组件接受的报告数。发送方客户端的令牌桶容量即为该数值;服务器的令牌桶深度为其 1.5 倍。UCFSettings::MaxReportsPerBatch(8)是驾驶中的客户端在一帧内发送的报告上限。UCFSettings::ScrapeReportInterval(0.1 秒)是同一组件两次刮擦报告之间的时间间隔。UCFSettings::CollisionRebuildThreshold(2 厘米)和UCFSettings::CollisionRebuildInterval(0.5 秒)控制凹陷车身的碰撞何时重新构建。只有当某个节点移动了这一距离,且距上次重建已过去至少该间隔,才会进行重建。UCFSettings::bDeformCollision(开)关闭时,会去掉跟随凹陷的全部开销:没有碰撞块,没有为被扯断部件做的切割,也没有为松脱部件做的凸壳。车辆随后按原本制作的碰撞体碰撞,因此被碰撞压入的汽车,对撞上它的东西来说并没有被压入,而被扯断的部件从车身碰撞体内部开始,由求解器将其推出。设备配置文件可以为性能较弱的设备设置Crushform.Collision.Deform 0。UCFSettings::CollisionDeferFrames(1)的取值为 0 或 1。取 1 时,一次较重的碰撞体构建在工作线程上运行:被扯断部件的切割、凹陷之后车身的重建,以及被扯断部件的凸壳。车身的重建和切割会在下一帧的物理之前落到车身上,如果到那时工作线程还没有完成,游戏线程会在那里等待它。命中的那一帧因此保持很短,而在较慢的机器上,下一帧可能会更长。0 表示在命中的那一帧完成全部构建。设备配置文件可以设置控制台变量Crushform.Collision.DeferFrames,它会覆盖项目中的值。UCFSettings::CollisionBlockTolerance(1.5 厘米)和UCFSettings::MaxCollisionBlocks(96)控制凹陷车身的包围盒和凸包被切分成多少个块。MaxCollisionBlocks是一个车身的所有包围盒和凸包合计被切分的最大块数。若该值不大于这些形状的数量,则不进行切分:每个形状仍保持为一个凸壳。
UCFSettings::DirtUpdateInterval(0.2 秒)是同一车身两次污垢更新之间的时间间隔。UCFSettings::DirtReferenceSpeed(8 m/s)是路面的速率按原样生效时的轮胎速度。UCFSettings::MaxDirtSpeedScale(2)限制轮胎速度更快时对这些速率的放大倍数。UCFSettings::DirtEventInterval(0.5 秒)和UCFSettings::DirtEventThreshold(0.02)限制同一车身的污垢变化事件。
轮胎预算决定哪些车轮会形变。UCFTireSettings::Scope 用于选择模式,预算的各项数值在 Crushform Tire 项目设置中设置;参见项目设置。每个数值也对应一个控制台变量,控制台命令或命令行参数设置它时会覆盖项目设置的值。所有变量都在控制台参考中有详细说明:
Crushform.Tire.MaxWheels(30):可同时形变的轮胎数量。观察者自己的车辆始终会形变,即使超出上限。Crushform.Tire.Radius(4000 厘米):其他车辆的轮胎可以形变的、距摄像机的距离范围。Crushform.Tire.LodDistance1(1500 厘米)和Crushform.Tire.LodDistance2(3000 厘米):轮胎改用更细的射线扇形追踪的距离,以及改用最细的扇形、并针对简单碰撞进行追踪的距离。Crushform.Tire.UpdateInterval(0.25 秒):两次预算计算之间的时间间隔。Crushform.Tire.Hysteresis(0.15):已获得形变资格的轮胎其边界扩大的幅度,以免位于边界上的轮胎闪烁。Crushform.Tire.OnScreenTolerance(0.5 秒):车轮上次被绘制之后,仍被视为在屏幕上的时间。Crushform.Tire.Enable(1):设为 0 后,每个轮胎都会恢复为圆形。
静止车轮的休眠没有控制台变量:UCFTireSettings::SleepDistance(1 厘米)和 UCFTireSettings::SleepAngleDeg(0.5 度):已停稳的车轮若保持在这些范围之内,可以进入休眠,此时它停止追踪,直到姿态改变。SleepDistance 为负数时,关闭休眠。
可破坏物与碎片
Section titled “可破坏物与碎片”UCFBreakableSettings::MaxLiveDebrisPieces(96)是每个世界中存活的碎片数量。超过该数量时,最旧的碎片会被回收。UCFBreakableSettings::MaxPersistentDebrisPieces(64)单独统计那些碎片持续到重生为止的定义所产生的碎片。UCFBreakableSettings::DebrisMaxSpawnDistanceCm(10000 厘米)为距离本地摄像机的距离,超过该距离的破坏不生成碎片,碎裂的玻璃板也不抛出碎片。UCFBreakableSettings::AnyBodyCheckIntervalSeconds(0.1 秒)是一道围栏(其单元会因任何物体而破坏)查找附近物体的频率。
Crushform.Glass.ShardScale(1)是每次碎裂中被抛出的碎片的比例,范围 0 到 1。每个碎片都是该玻璃板 Niagara 系统的一个粒子,所以数量就是一次碎裂的开销。一次碎裂最多抛出UCFGlassDefinition::MaxShardTiles乘以该定义每个分块的碎片数:夹层预设最多 60 个(12 × 5),钢化预设最多 64 个(16 × 4)。0.5 大约抛出一半,0 则一个也不抛:玻璃板仍会碎裂,只是没有粒子。Crushform.Glass.MaxLiveShards(512)是碎裂玻璃板的碎片同时存活的最大数量,0 表示不设上限。它限定了多块玻璃板一起碎裂的堆积情形的开销:512 约合八次夹层玻璃碎裂,足以容纳一辆车的所有玻璃板。超过上限时,最旧的碎裂玻璃板的碎片最先被释放,同一次碎裂自己的碎片超出上限的部分会被裁掉。Crushform.Glass.ShardSystemsPerFrame(1)是一帧内启动的碎片系统数量,0 表示不限。其余的在之后的帧里按顺序启动,并按它们等待的时间沿各自速度向前移动,最多 0.25 s。这样可以避免堆积情形中碎裂的玻璃板挤在同一帧里;如果你的游戏能负担这一帧,并希望在碰撞的瞬间看到全部碎片,就把它调高。- 每块碎裂的玻璃板占用一个池中的 Niagara 组件来抛出碎片,并在碎片结束时、玻璃板被修复时或游戏结束时归还。所以池中每块碎裂的玻璃板占一个组件,而不是每个碎片一个。
撞击反馈与滚动 FX
Section titled “撞击反馈与滚动 FX”UCFImpactFeedbackSettings::MaxAudibleDistanceCm(6000 厘米)和UCFImpactFeedbackSettings::MaxEffectDistanceCm(8000 厘米):距离本地摄像机超过这些值的撞击不播放声音,也不生成特效。UCFImpactFeedbackSettings::MaxVoiceSeconds(3 秒)是一个已播放的声音占用发声槽位的最长时间。撞击集合中的每一行都有自己的FCFImpactFeedbackEntry::MaxConcurrentVoices(默认 4),即该行中可同时播放的声音数量。UCFImpactFeedbackSettings::MaxSoundsPerFrame(2)是一帧内启动的声音数量上限,0 表示不设上限。其余的按从强到弱的顺序等待之后的帧。UCFImpactFeedbackSettings::SoundQueueSeconds(0.15 秒)是超出上限的声音在被丢弃之前最多可以等待多久。设备配置文件可以设置Crushform.Impact.MaxSoundsPerFrame和Crushform.Impact.SoundQueueSeconds。UCFWheelSettings::FXTuning会在车辆速度较慢时停止其滚动 FX。FCFRollingFXTuning::SleepSpeedKPH默认为 1 km/h。
分析一次碰撞
Section titled “分析一次碰撞”一次碰撞的命中路径大多在游戏线程上分几个阶段运行,每个阶段都有各自的命名范围。要查看时间花在哪里,请在碰撞之前输入 stat namedevents,再输入 Trace.Start cpu,frame,bookmark,碰撞之后输入 Trace.Stop,然后在 Unreal Insights 中打开追踪:下面的每个范围都会以其名称出现。当 UCFSettings::CollisionDeferFrames 大于 0 时,切割和凸壳在工作线程上运行,下面的切割范围也包括在内;Body collision block convex 无论如何都在工作线程上运行。这些范围按阶段分组如下:
- 命中输入:
Deform Hit gate、Deform Ignored actors、Deform Hit mass、Deform Hit giving way、Deform Hit contacts、Deform Hit distance、Deform Hit velocities和Deform Hit root pose。 - 晶格与报告:
Deform Mark chunks、Deform Debug hit、Deform Predict、Deform Damage schedule、Deform Render mark、Deform Part damage、Deform Shake off和Deform PartCollision wait。 - 车身碰撞体:
Body collision cut subtract、Body collision cut prepare、Body collision cut watch、Body collision block convex、Collision blocks clip convex、Deform Collision poll、Body collision job start、Body collision job wait和Body collision job apply。 - 铰接部件:
Hinge crowded、Hinge blocked、Hinge detach、Hinge start swing、Hinge loosen、Hinge joint create和Hinge joint destroy。 - 车身距离:
Body distance、Body distance pose和Body distance shapes。 - 玻璃碎片:
Glass Shards、Glass Shard data、Glass Shard spawn、Glass Shard hits和Glass Apply verdict。 - 撞击反馈:
Play Impact sound、Play Impact effect和Impact sound queue。
车身碰撞体的构建在工作线程上运行:碰撞那一帧显示任务的启动,它会复制工作线程要读取的晶格;任务落地的那一帧显示它的应用。当截止时间先于工作线程完成而到来,或者仍在运行的构建被丢弃时(修复、重新挂接、车身被重建或丢失、游戏结束),就会出现等待。
检查是否正常工作
Section titled “检查是否正常工作”使用 Play In Editor 在包含受损车身的关卡中运行,然后打开控制台。
Crushform.Stats首先输出图集信息,格式如下。等待中的车身数量或驱逐次数不断增长,说明图集已满。
Crushform atlas: <used> of <total> slots used, <waiting> waiting, <evictions> evictions, <uploads> uploads.随后,它会为世界中每个可受损的 Actor 输出一行:server lattice 表示本机持有损伤数据,client view 表示本机绘制的是服务器的数据。该行之后还包括 Actor 的代数、待处理的报告和数据块,以及其计数器:撞击次数、已发送、已接受和已拒绝的报告数、碰撞构建次数及其中最长一次的耗时(毫秒)、碰撞等待次数(游戏线程在截止时间等待过的构建)、被扣住的部件数(掉落前等待过自己的切割的部件),以及各部件的凸壳。专用服务器进程不绘制任何内容,它会输出 Crushform atlas: none in this process (a dedicated server draws nothing). 来代替第一行。
stat Crushform会在屏幕上显示核心模块的计时步骤,例如形变更新、污垢更新和车身碰撞重建,均以毫秒为单位。其他统计组包括CrushformTire、CrushformBreakable、CFBreakableInstances、CrushformDebris、CFPropContact、CFImpactFeedback、CrushformVehicle、CrushformChaos、CrushformWheel、CrushformEngine、CrushformPlayground和CrushformDebug。
一些受损车辆上的凹陷停止更新。
原因:图集已满。距离最远的受损车身会等待槽位,并以未受损的状态绘制,直到有槽位空出。Crushform.Stats 会显示等待数量和驱逐次数。
解决:增大 UCFSettings::Atlas。槽位数量为图集尺寸除以槽位尺寸,上限为 4096 纹素,因此更大的图集可同时容纳更多受损车身。
凹陷从不出现,日志提示槽位过小。
原因:UCFSettings::SlotWidth 小于 16 纹素,或 UCFSettings::SlotHeight 小于 4。
解决:将槽位尺寸提高到至少 16 乘 4 纹素。默认值为 256 乘 8。
凹陷从不出现,日志提示图集的像素格式。 原因:图集不是线性的 B8G8R8A8。sRGB 贴图或任何其他格式都会被拒绝。 解决:使用 RTF_RGBA8 渲染目标,或关闭 sRGB 的 BGRA8 贴图。