Unity Write Default Bugs

Unity 动画控制器中 WriteDefault 问题的整理

关于这篇文章
本文为 Unity 动画控制器中 WriteDefault 问题的整理,用于 VRChat 改模参考, 目前的内容来自 Write Default Bugs in Unity | VRCFury

Unity 中的 Write Defaults 问题

Write Defaults (写入默认值) 会导致大量未记录的 Unity Bug,其中许多问题至今仍在被发现。以下是我们目前已知的问题:


条件:

  • 控制器包含 Write Defaults (WD) 开启和关闭的混合状态
  • 一个 WD 关闭的状态位于包含 WD 开启状态的层中或之下

结果:

  • 控制器中的随机属性将“粘住”,即使动画指示它们改变,它们也拒绝更改。

可能的解决方法:

  1. 不要在控制器中混合使用 WD(除非在直接 BlendTree 和 Additive 层中,这些地方必须始终开启 WD)
  2. 如果必须混合使用,请确保所有 WD 开启的状态位于 WD 关闭状态的下方
  3. 请注意,在 VRChat 头像中,所有可播放层控制器都被视为一个“控制器”

条件:

  • 包含直接 BlendTree 的状态或 Additive 层中的状态设置为 WD 关闭

结果:

  • 控制器中的随机属性可能每帧增长或缩小,导致它们无限制地偏离
  • 在控制器中动画的 BlendShapes 可能会意外地乘以 2 倍或 3 倍

可能的解决方法:

  1. 确保所有直接 BlendTrees 和 Additive 层中的所有状态始终开启 WD

条件:

  • 混合器中的多个控制器使用 WD 关闭(例如 Gesture 和 FX)

结果:

  • 混合器中最低的控制器(通常是 FX)将宣称所有未掩码的变换的所有权
  • 即使这些变换在控制器中的任何状态中都没有动画,它仍将阻止混合器中的任何更高控制器对它们进行动画处理

可能的解决方法:

  1. 使用 WD 开启
  2. 合并 Gesture 和 FX,这样 FX 宣称所有变换是可以接受的(因为所有变换动画都在一个控制器中)
  3. 为 FX 添加掩码,防止其拥有特定变换(在某些情况下由于掩码层中的属性破损而无法实现)

条件:

  • 混合器中的多个控制器对同一人形肌肉进行动画处理

结果:

  • 混合器中最低的控制器(通常是 FX)将宣称所有未掩码的肌肉的所有权
  • 即使这些肌肉在控制器中的任何状态中都没有动画,它仍将阻止混合器中的任何更高控制器对它们进行动画处理

可能的解决方法:

  1. 确保每个肌肉只由一个控制器进行动画处理
  2. 如果需要覆盖,使用 Playable Layer Control 在动画完成时将覆盖控制器的权重设置为 0(如在 Action 中所做的那样)

条件:

  • 单个控制器中的多个层使用 WD 关闭
  • 两个层对人形角色的同一肌肉进行动画处理

结果:

  • 最低的层在第一次对肌肉进行动画处理时“宣称”肌肉的所有权,阻止任何更高的层对该肌肉进行动画处理
  • 移动到不再对肌肉进行动画处理的状态不会释放所有权

可能的解决方法:

  1. 使用 WD 开启
  2. 使用 Animator Layer Control 将较低层的权重设置为 0

条件:

  • 状态的层或控制器的基础层包含一个不允许所有变换的掩码

结果:

  • 状态无法对材质槽 0 进行材质交换,如果它不在掩码中允许的变换内
  • 状态无法对大于 0 的材质槽进行材质交换
  • 状态无法对 VRC Physbone(以及可能的其他非标准组件类型)进行属性动画处理

可能的解决方法:

  1. 不要在层或控制器的基础层上使用掩码

条件:

  • 状态使用 WD 关闭
  • 状态在根运动或任何 BlendTree 子项中包含“无”动画或空动画剪辑

结果:

  • 类似于混合 WD 的症状

可能的解决方法:

  1. 如果状态使用 WD 关闭,确保所有运动和 BlendTree 子项都设置为包含至少一个属性的动画剪辑(它不必有效)

条件:

  • WD 开启
  • 一个层中的动画剪辑设置了一个属性
  • 在较低层的 BlendTree 中以部分权重 >0 修改了相同的属性

结果:

  • 最终属性值不考虑第一个层中的值

例如:

  • 如果属性的默认(静止状态)值为 0
  • 属性在层 1 中被动画设置为 5
  • 属性在层 2 中以 0.1 的权重被动画设置为 10
  • 最终值将是 1(完全忽略了 5)
  • 然而,如果层 2 的权重被更改为 0,最终值突然变为 5

可能的解决方法:

  1. 不要在多个层中动画相同的属性,如果它们涉及“开放式”混合
  2. 所有涉及在较高层动画的属性的 BlendTrees 都应完全动画所有子项中的共享属性
  3. 涉及在较高层动画的属性的直接 BlendTrees 应始终具有权重 1(完全动画)或 0(传递到上层)

条件:

  • WD 开启
  • 动画中的任何参数由动画控制
  • 一个状态过渡到另一个使用 BlendTree 的状态,当前混合涉及多个运动

结果:

  • 过渡忽略了正在过渡的状态,立即跳到新状态

可能的解决方法:

  1. 使用 WD 关闭
  2. 完全避免这种情况(不要在多状态层中使用 BlendTrees)
  3. 不要使用动画参数(通常无法避免)