跳转到内容
CRUSHFORMV1.1.0
在 Fab 上获取

损伤损伤区域与事件

损伤区域与事件

损伤区域告诉你的游戏,车身每一侧的凹陷有多严重。车身共六侧:前、后、左、右、上、下。每一侧报告其最深的凹陷和平均凹陷,取值从未受损车身的 0 到凹陷已达到其允许上限的 1。当任一侧发生变化时,事件 On Damage Changed 会被触发,使你的游戏能够对损伤作出反应,例如亮起警示灯、降低最高速度或计分。

六侧。 每一侧是车身沿根组件某一轴向的外侧三分之一。前侧为根的 +X,后侧为 -X,左侧为 -Y,右侧为 +Y,上侧为 +Z,下侧为 -Z。相邻的侧面在边缘处重叠,因此靠近拐角的凹陷会同时计入两侧。

最大值与平均值。 对每一侧,Max 是该侧最深的凹陷:晶格节点的最大位移,除以配置文件的 Max Displacement,并限制在 1 以内。Mean 是该侧所有节点上同一数值的平均值。两者的取值都在 0 到 1 之间。

任意盒体。 GetDamageInBox 可针对你选定的盒体,例如大灯周围的区域,返回相同的两个数值。该盒体位于根组件的空间中,与玻璃板的 Crush Link Box 处于同一空间。

仅计已确认的损伤。 区域读取的是服务器已确认的损伤。在客户端上,你预测的命中在服务器确认之前不会计入区域。因此,事件在每一端报告的数值都相同,而被服务器拒绝的命中永远不会显示。

事件何时触发。 事件每帧至多检查一次,并且是在车身晶格发生变化之后。只有当区域与上一次报告的内容不同时,它才会触发。它在每一端都会触发,包括专用服务器。修复会以零值触发一次该事件。中途加入的玩家,会在其所在的端上由复制的损伤构建出晶格之后,收到该事件。

所需条件。 车辆适配器需要开启 Dirt and Dents,配置文件需要开启 Dents。否则,区域读数为零,事件也永远不会触发。适配器会转发该事件以及两个获取函数,因此你可以直接绑定到车辆的适配器,而无需找到形变组件。

损伤区域与刚度区域不是同一回事。刚度区域是使车身的某部分变得更硬或更软的盒体,Crushform.ShowZones 会绘制它们。损伤区域只报告已经发生的损伤。关于刚度区域,参见软区。

  1. 打开车辆的蓝图,例如 BP_VehicleAdvSedan 的副本。选中其 Crushform Chaos Vehicle Adapter 组件,并确保 Dirt and Dents 已开启。在关卡中放置第二辆车,供下面的检查使用,并使它远离你驾驶的车。
  2. 打开车辆的形变配置文件,确保 Dents 已开启。参见凹陷与晶格。
  3. 无需再创建任何其他内容。区域来自车身的晶格。下一节说明如何读取它们。

在蓝图中,将 On Damage Changed 绑定到车辆的适配器上。该事件以 Zones 的形式传递六侧数据。拆分 Zones 以获取 Front,再拆分 Front 以获取其 Max,并将其打印出来。同样的引脚可以得到其他各侧的数据,把 Max 换成 Mean 即可。

每当事件触发时,此图打印前侧的 Max。

此图每次触发事件时都会打印前侧的 Max。它打印的是一个裸数字,没有标签:只有数值,没有侧面的名称。该事件也通过相同的引脚传递到其他每一侧。

在 C++ 中,将 lambda 绑定到形变组件的原生事件上,并以相同方式读取盒体。原生事件会在蓝图事件之前触发,且传递的区域数据相同。车身碰撞体跟随的正是同样的凹陷。

#include "CFDamageTypes.h"
#include "CFDeformComponent.h"
Deform->OnDamageChangedNative.AddLambda([](const FCFDamageZones& Zones)
{
UE_LOG(LogTemp, Log, TEXT("Front max %.2f"), Zones.Front.Max);
});
const FCFDamageValues Nose = Deform->GetDamageInBox(NoseBox); // NoseBox: an FBox in the owner's root space

Deform 是车身的 UCFDeformComponent。NoseBox 是根组件空间中的 FBox。

属性作用默认值
UCFVehicleAdapterComponent::bDirtAndDents为车辆开启损伤。关闭时:区域读数为零,事件永不触发。开
UCFProfile::bDents命中和挤压是否会使车身凹陷。关闭时:区域永不改变。开
UCFProfile::MaxDisplacement计为完全凹陷的位移(cm)。Max 和 Mean 都以它为除数。60

没有其他设置会改变区域。数值来自车身的晶格。

在除 Shipping 之外的任何构建中,于编辑器内运行。Crushform.DebugImpact 不会命中你驾驶的车辆,因为轨迹会跳过它。因此,请使用带有图表的第二辆车的副本,停放在远离你自己车辆的地方。从其正面接近它,然后输入 Crushform.DebugImpact 10 <name>,并用你副本在 World Outliner 中显示的名称的一部分代替 <name>。命中会瞄准该车车身上离其中心最近的那一点,从你所在的位置看去,所以从正面接近时,命中落在车的前部。事件会触发,图表打印前侧的 Max。正面的命中应打印出大于零的数值。

若要检查后侧,将图表的断开引脚从 Front 改为 Back,然后从副本的后方接近,并以相同方式命中。运行 Crushform.RepairAll:每一侧都会回到零,并且事件会以零值触发一次。

在权威端,CFScriptedHits::ApplyScatteredHits 会在车身的随机点上施加若干次命中。调试模式的预设使用了它。

  • On Damage Changed 从不触发。 车辆适配器上的 Dirt and Dents 已关闭,或配置文件中的 Dents 已关闭,或车身没有配置文件。请开启这些开关,并指定一个配置文件。
  • 命中车辆后,区域立即显示为零。 在客户端上,你自己的命中只是预测,直到服务器确认为止,而区域只计入已确认的损伤。请稍等片刻,等待服务器的回应,或在服务器上读取区域。
  • 在一处可见的凹陷上,盒体读数为零。 盒体不在根组件的空间中,或位于车身晶格之外,或尚未设置。请在车身所属根组件的空间中构建盒体,即与根组件的轴相同的空间。
  • 前后看起来对调了。 各侧沿根组件的轴划分,以 +X 为前。如果车辆网格体的朝向不同,需要旋转其根组件以使其匹配。请检查根组件的旋转。