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

入门故障排除

故障排除

下面每个问题都给出了原因和解决方法。如果插件会在日志中写入一行,代码块中显示的是源码里的格式字符串:%s 是对象路径,%d 是数字。警告和错误会出现在 Output Log 中的 LogCrushform 和 LogCrushformWheel 下。Crushform.Stats 的输出行即该命令打印的内容。

原因。 没有 Crushform 配置文件(UCFProfile),UCFDeformComponent 就不会做任何事。在设置配置文件之前,它不会铺设晶格,也不会为此写入日志行。未设置 Deform Profile 的车辆适配器会使用项目的默认配置文件。

如果已经设置了配置文件,但拥有者没有可以弯曲的网格体,组件会保持关闭,并写入:

%s has a profile but no deformable mesh components; Crushform stays off

解决方法。 创建一个 UCFProfile 数据资产,并将其设置到组件上:可以在类默认值中设置,也可以在 SpawnActorDeferred 和 FinishSpawning 之间设置。网格体方面的内容见下面各节。

网格体没有凹陷,因为它的材质没有连接

Section titled “网格体没有凹陷,因为它的材质没有连接”

原因。 网格体只通过其材质显示凹陷。MF_CF_Deform 移动顶点并转动法线,它必须连接到 World Position Offset 和 Normal。否则网格体不会移动。

解决方法。 连接每个应当弯曲的网格体的所有材质:将 MF_CF_Deform 接到 World Position Offset 和 Normal,将 MF_CF_Paint 放在你的漆面与 Base Color、Roughness 和 Metallic 之间,并由 MF_CF_Deform 提供 Wear Depth 和 Scratch。在 Python 中,unreal.CFContentLibrary.wire_material(material, deform, paint, max_displacement + fold_amplitude) 会完成以上全部操作。

原因。 只有静态网格体和蒙皮网格体会弯曲。实例化静态网格体从不弯曲,因为它的所有实例共享同一个基元。此外,配置文件中的 Include Tags 和 Exclude Tags 会过滤其余网格体:如果 Include Tags 不为空,网格体需要带有其中一个标签;带有任何一个 Exclude Tags 标签的网格体会被跳过。

解决方法。 将网格体放在普通的静态网格体组件中,而不是实例化组件中。检查网格体的组件标签是否与配置文件的 Include Tags 和 Exclude Tags 相符,然后删除该标签,或修改这些列表。相对车身会移动的部件应当被排除;参见“移动的部件弯曲错误”。

原因。 速度变化量(delta V)不高于 Min Delta V 的命中不会留下凹陷。默认值为 0.5 m/s。这种命中仍可能算作刮擦。

解决方法。 如果希望较小的命中也能造成凹陷,请在配置文件中降低 Min Delta V。若要用更猛的命中进行测试,可以运行 Crushform.DebugImpact [DeltaV] [Name]:它默认以 10 m/s 命中准星下的 Actor。这是作弊指令,除 Shipping 之外的所有构建中都存在。

原因。 只有在 Dirt and Dents 开启时,车辆适配器才会创建形变组件。玻璃板和车轮的污垢同样需要它。

解决方法。 在适配器上勾选 Dirt and Dents。

原因。 图集有固定数量的槽位,默认 128 个,每个为 256x8 纹素。所有槽位都被占用时,受损的 Actor 会等待空闲槽位;离玩家摄像机最远的受损 Actor 会以未受损的状态绘制,直到有槽位释放。Crushform.Stats 会输出槽位数量:

Crushform atlas: %d of %d slots used, %d waiting, %d evictions, %d uploads.

解决方法。 将 Atlas(Project Settings › Plugins › Crushform › Atlas)指向你自己的、更大的 RGBA8 渲染目标,每边最多 4096 纹素。槽位数为其尺寸除以 Slot Width,再除以 Slot Height。

原因。 晶格在 BeginPlay 时固定到根组件上。之后才移动的网格体会以其 BeginPlay 时的姿态弯曲。车门和方向盘就是典型例子。

解决方法。 按标签排除该部件,方法见“部分网格体不会凹陷”。

连接后材质无法编译:它已经读取两个参数集合

Section titled “连接后材质无法编译:它已经读取两个参数集合”

原因。 一个材质最多只能引用两个材质参数集合(Material Parameter Collection)。连接 MF_CF_Paint 或 MF_CF_WheelDirt 会添加污垢集合,因此已经读取两个集合的母材质将无法编译。

解决方法。 在连接之前为污垢集合留出位置:母材质最多只能再引用一个其他集合。例如,先将第二个集合的参数移到第一个集合中,然后再重新连接。

连接被拒绝:材质使用世界空间法线

Section titled “连接被拒绝:材质使用世界空间法线”

原因。 MF_CF_Deform 在切线空间中工作。使用世界空间法线的材质会被拒绝,连接保持不变:

WireMaterial: %s takes a world-space normal; MF_CF_Deform works in tangent space

解决方法。 将材质设为切线空间法线(Tangent Space Normal 选项),然后重新连接。

在 Nanite 上,凹陷在屏幕边缘闪烁

Section titled “在 Nanite 上,凹陷在屏幕边缘闪烁”

原因。 Nanite 按 World Position Offset 的边界进行剔除。如果 Max World Position Offset Displacement 短于最深凹陷加上褶皱幅度,靠近屏幕边缘的凹陷就会闪烁。配置文件中的 Max Displacement 是任何节点移动的最大距离,车身材质必须使用它。

解决方法。 重新连接材质:连接时如果边界过小,会将其增大。也可以手动将 Max World Position Offset Displacement 设为配置文件的 Max Displacement 加上材质的 Fold Amplitude。

原因。 骨骼网格体的着色器只有在材质标记为 Used with Skeletal Mesh 时才会编译。插件自带的车辆母材质已做此标记。

解决方法。 在材质的 Details 中,于 Usage 下勾选 Used with Skeletal Mesh。

原因。 只有在 Project Settings > Plugins > Crushform 中设置了 Surfaces 资产,车身才会变脏。没有设置时,没有任何车身会变脏。如果已设置的资产加载失败,日志会显示:

Crushform surfaces %s do not load; bodies stay clean

污垢还需要车轮宿主:没有向它报告车轮的车身不会获得污垢,污垢计时器也不会起作用。

解决方法。 将 Surfaces 设为 /Crushform/Surfaces/DA_CF_Surfaces,或设为你自己的表。添加车辆适配器(或能回答车轮问题的宿主)。然后检查 Dirt and Dents 是否开启。

原因。 专用服务器不绘制污垢,因此在那里看不到污垢。在服务器上,Crushform.Stats 会这样输出:

Crushform atlas: none in this process (a dedicated server draws nothing).

污垢事件 OnDirtChanged、OnWashed 和 OnWheelSurfaceChanged 在专用服务器上永远不会触发。

解决方法。 在客户端上查看污垢。AddDirt 和 WashAt 只改变本机的污垢,因此需要在每个应当显示结果的端上调用它们。Wash 是对整个车身的联网清洗,仅限权威端调用,并会清洗每个端上的污垢。

原因。 车轮会读取 Surfaces 表中与其地面物理材质对应的那一行。没有对应行的材质使用 Default 行。该行的 Dirt 速率决定了路面给车身带来多少污垢,因此,Dirt 为零的 Default 行会使任何没有自己一行的地面都不留下污垢。

解决方法。 为地面设置插件提供的某种物理材质,例如 /Crushform/Surfaces/PM_CF_Asphalt,或你自己的物理材质。然后在 Surfaces 表中为它添加一行,并设置 Dirt 速率。

车轮只是一根骨骼,因此没有污垢

Section titled “车轮只是一根骨骼,因此没有污垢”

原因。 只是一根骨骼的车轮没有可以沾污或形变的车轮网格体,因此既没有污垢,也没有轮胎形变。Chaos 适配器会从移动组件中读取车轮的骨骼名称。

解决方法。 为车轮设置一个网格体,使其有可以沾污的对象。

原因。 车轮的材质没有经过 MF_CF_WheelDirt。插件的车轮材质是这样构建的:Base Color、Roughness 和 Metallic 都经过 MF_CF_WheelDirt。

解决方法。 使用 /Crushform/Materials/M_CF_Wheel。或者自行将 MF_CF_WheelDirt 接到车轮的 Base Color、Roughness 和 Metallic 上。

车轮的材质使用了 MF_CF_Deform 或 MF_CF_Paint,却没有凹陷和车轮污垢

Section titled “车轮的材质使用了 MF_CF_Deform 或 MF_CF_Paint,却没有凹陷和车轮污垢”

原因。 车辆适配器从不使车轮网格体或挂在其下的任何东西发生形变,因为车轮会随车身的晶格转动。因此,车轮上的车身材质(MF_CF_Deform 或 MF_CF_Paint)永远不会产生凹陷,只有 MF_CF_WheelDirt 会绘制车轮污垢。

解决方法。 从车轮的材质中移除 MF_CF_Deform 和 MF_CF_Paint。保留 MF_CF_WheelDirt,以及在 Tire Deform 开关下的 MF_CF_TireDeform。轮辋上请保持 Tire Deform 关闭。

原因。 在以下四种情况下,滚动声音会保持静音:

  • Project Settings > Plugins > Crushform Wheels 中的 Rolling Sound 开关已关闭。

  • Attenuation 为空。声音保持关闭,日志会显示:

    %s: no Attenuation in Project Settings > Plugins > Crushform Wheels; the rolling sound stays off
  • 地面所在的那一行没有 Rolling Sound。空字段即为静音,该行不会借用 Default 行的声音。

  • 附近没有听者。只有当听者位于衰减范围之内时,声音才会播放。

解决方法。 勾选 Rolling Sound。将 Attenuation 设为 /Crushform/Sounds/SA_CF_TireRolling。为地面所在的那一行设置 Rolling Sound,例如 /Crushform/Sounds/SW_CF_Tire_Asphalt_Loop。然后站到范围之内。

原因。 对于一个车身,有一个端是撞击源,默认是权威端。既不是权威端也不是撞击源的端不会应用它自己的命中。模拟该车身的端就是撞击源:它自己的上报会携带凹陷。另外,服务器会拒绝任何比 Max Plausible Delta V 更猛烈的上报,该值默认为 40 m/s。

解决方法。 在你的 ICFDeformHost 中,让 IsCrushformImpactSourceHere 在模拟车身的端上返回 Yes。如果你的命中比 Max Plausible Delta V 更猛烈,请提高该上限,否则服务器会拒绝这些上报。在服务器和客户端上用 Crushform.Stats 比较网络和命中计数器。

原因。 所有 Crushform 控制台命令都会在 Shipping 构建中被编译掉。Crushform.Debug、Crushform.ShowZones、Crushform.ShowCollision、Crushform.RepairAll 和 Crushform.DebugImpact 是作弊指令;它们存在于除 Shipping 之外的所有构建以及编辑器中。

解决方法。 在编辑器或非 Shipping 构建中测试这些命令。不要依赖随产品发布的代码中的 CrushformDebug(参见安装)。

蓝图宿主的回答在预览中不可见

Section titled “蓝图宿主的回答在预览中不可见”

原因。 编辑器预览不会运行蓝图宿主的回答。当 Actor 所在世界的 Actor 尚未初始化时,AActor::ProcessEvent 会跳过该 Actor 上的脚本,预览中正是这种情况。因此 Details 面板和区域编辑器看不到蓝图的回答。

解决方法。 在 Play In Editor 中检查回答,那时 Actor 已经初始化。

原因。 宿主按 Actor 和接口分别保存。同一 Actor 和接口的第二个宿主会替换第一个,并给出警告:

Host %s replaces host %s for %s under %s

解决方法。 每个 Actor 和接口只保留一个宿主,并移除你不需要的注册。

原因。 未实现该接口的对象会被拒绝。在 C++ 中,注册表会写入日志:

Host %s does not implement %s, so it cannot answer for %s

在 BeginPlay 之后通过 SetCrushformHost 设置的宿主同样会被拒绝:

%s: SetCrushformHost after BeginPlay is refused; the host is read once, in BeginPlay

解决方法。 在蓝图中,打开 Class Settings,在 Implemented Interfaces 下点击 Add,然后实现其函数。在 BeginPlay 之前调用 SetCrushformHost。

  1. 在 Play In Editor 中重新运行关卡,并重现问题。
  2. 打开控制台,运行 Crushform.Stats。它会输出正在使用的图集槽位、等待中的槽位,以及每个可受损 Actor 的计数器。如果有槽位在等待,请参见“部分受损车辆的凹陷停止显示”。
  3. 运行 Crushform.Debug 1。它会绘制受损的晶格节点和最近的命中,让你看到车身在哪里产生了凹陷。
  4. 在 Output Log 中检查是否有新的 LogCrushform 和 LogCrushformWheel 行。