Skip to main content

Write Defaults

文章原址:https://notes.sleightly.dev/write-defaults/

Write Defaults

Write Defaults 是动画状态(Animator States)的一个可选项,这对许多虚拟形象创作者来说都是一个令人头疼的问题,因为它们的行为表现比较反直觉。预期行为如下:

Write Defaults 字段决定动画中所做的更改是否是持久性的。

如果启用了 Write Defaults 字段,则动画字段将在离开动画状态时恢复默认状态。

如果禁用了 Write Defaults 字段,则将保留更改。

默认情况下,Unity 会在新创建的状态上启用 Write Defaults,但 VRChat 提供的示例动画控制器是关闭 Write Defaults了 的。

Untitled.png

默认的动画状态为开启 Write Defaults

示例:

如果您有一个在 Hierarchy 中被禁用(即默认情况下关闭)的帽子(hat),并且您有一个看起来像这样的层级:

Untitled.png

在 Write Defaults On 的情况下:

  • 当进入 Hat On 的状态时,帽子会切换为开启状态
  • 当回到 Hat Off 的状态时,帽子会切换为关闭状态(因为这是默认状态) 

Write Defaults Off 的情况下: 

  • 当进入 Hat On 的状态时,帽子会切换为开启状态
  • 当进入 Hat Off 的状态时,帽子将保持开启状态(因为您没有特别将其切换回关闭状态或写回默认值)

操作指南

在使用 Write Defaults Off 时,请遵循以下几条操作指南。我也将在下方解释原因(仅为完整性起见):

  • 请勿在单个控制器中混合 Write Defaults。混合的 Write Defaults 将表现得像 Write Defaults Off
    • 此条的例外状况为那些具有单个状态的层。这些层可以(并应该在 Direct Blend Trees 的情况下)被设置为 Write Defaults On
    • 由于它们永远不会离开自己的状态,因此这样做是可以的,我们从不依赖 Write Defaults On 行为。
  • 请勿在 Direct Blend Trees 上使用 Write Defaults Off
  • 如果您正在使用 Write Defaults Off,则您的所有状态都应包含一个 Animation Clip 或一个 Blend Tree。这个 Animation Clip 可以是空的,但通常建议使用某种绘制了持续两帧不存在的 GameObject 的 Animation Clip(有时称其为buffer clip)。
  • 请注意,用 Write Defaults Off 绘制变换动画会覆盖其他正在播放的 Animator Controllers 中的所有变换动画。对于 VRChat 则具体来说:如果您正在绘制 FX 层中的任何变换,它将覆盖 Gesture 层中的所有变换,除非您应用一个仅启用变换动画并禁用所有其他变换的虚拟形象遮罩,并将此遮罩应用到您的 FX 层动画层。

有关遮罩的更多信息,请参阅“Avatar Masks”页面。

请注意:如果您因 Gesture 和 FX 层中的 Write Defaults Off 变换动画而必须使用遮罩,则不能在除第一个插槽之外的任何插槽上使用 matswaps,因为无论遮罩是否启用,被遮罩的变换(无论是启用还是禁用)都不能在除第一个材质插槽之外的其他材质插槽上具有 matswaps 动画。

VRLabs 的 Avatar 3.0 Manager 是用于检查您是否违反了这些规则的实用工具(检测至少前两条规则) 。在该工具的 Write Defaults 选项卡中,它会告诉您是否混合了 Write Defaults,并会在您按下相应按钮时为您自动设置。请注意,它不会为 Direct Blend Trees 进行例外规避,因此它们的动画状态必须在其名称中包含(WD On)以将其标记为 Write Defaults On

解释

不要在单个控制器中混合 Write Defaults

处于单个 Write Defaults Off 状态将导致所有其他 Write Defaults On 状态不写入其默认值,因此表现为 Write Defaults Off方式。

不要在 Direct Blend Trees 中使用 Write Defaults Off

 Write Defaults Off 的 Direct Blend Trees 会展示一些奇怪的行为,例如影响其他在使用相同参数的 Direct Blend Trees,并且还会随着时间的推移乘以它们的结果,导致意外结果的发生。通常应永远不被使用。

为了更清楚地说明乘法行为,最终结果是,在 Write Defaults Off 的 Direct Blend Trees 中,最终的权重会乘以一个因子x/(1-yx),其中x是当前子级的权重,y是其他子级的权重之和,除以当前子级的权重。请注意,如果这个分数的分母为0或更低,则数值变为无穷大且永远不会停止增加。这意味着,如果您有n个子级,并将每个子级的权重设置为1/n,则最终结果是乘数为1,因此这允许您使用 Write Defaults Off 的 Direct Blend Trees。然而,这并不意味着这样做就是明智的,因影响其他混合树和表现出其他奇怪的行为使得使用 Write Defaults On 更为简单。

如果您正在使用 Write Defaults Off,则您的所有状态都应包含一个动画切片或 Blend Tree。

不包含任何动画的 Write Defaults Off状态可以用它们来自的 Animator State 中的动画剪辑的默认值覆盖先前图层中的动画剪辑。

优点/缺点

Write Default On

优点:

  • 由于可以使用空状态/缓冲状态来恢复到默认上传行为,因此不太复杂
  • 允许在 FX 层上对变换动画进行变换,而不会覆盖手势层
  • 在基本2状态切换中,比 Write Defaults Off 降低了33%的帧时间(在Unity 2019中)
  • 更容易更改默认值(如果您依赖上传状态)

缺点:

  • 依赖上传状态
  • 通常在使用 Mixed Write Defaults 时会出现问题
  • 不允许在不使用参数驱动程序或 AAP 的情况下进行顺序操作

Write Default Off

优点:

  • 不依赖于上传状态
  • 通常与混合写入默认值兼容
  • 允许顺序操作

缺点:

  • 在空状态中需要缓冲动画
  • 在没有遮罩的情况下对变换进行动画处理时,会覆盖所有手势变换
  • 在基本2状态切换中,比 Write Defaults On 增加了50%的帧时间(在 Unity 2019中)

创作指南

当创建应与 Write Defaults On 和 Write Defaults Off 兼容的预制件时,这些指南将非常有用:

  • 请确保每个图层始终通过其自身的一组属性进行动画处理(例如,图层中的每个状态都应动画化相同的一组属性)。
  • 如果需要在多个图层上动画化某个属性,请确保每个状态都具有动画效果,了解较低图层会覆盖较高图层,并始终在顶部提供一个具有默认状态的“重置”图层。

如果您遵循本文档中概述的指南,每个属性都将始终动画化,并且您的系统将始终与 Write Defaults On 和 Write Defaults Off一起正常工作。

Blendshape 值翻倍

在非常特定的条件下,当依赖于 Write Defaults On 时,Blendshape 值会翻倍。

(例如:您有一个空的 Write Defaults On 状态,它过渡到一个绘制 Blendshape 的 Write Defaults On 状态。当处于空的 Write Defaults On 状态时,绘制 Blendshape 的默认值会乘以3。)

这个问题比其他问题更加微妙和模糊,所以不要把我们在这里说的话当作事实,而更多地当作观察结果:

  • 它似乎是由 Write Defaults Off 了的 Additive layer 引起的。
  • 它被一个只有“关闭默认写入”状态(如默认状态)的手势层所阻止。单个播放“默认写入开启”状态会导致它再次发生。
  • 它与任何遮罩和实际可到达的动画都无关。只需存在于图层上就足够了。
  • 只要您使用值0-100,它就不会影响其行为,因 03=0 并且 1003=100 (因 Blendshape 钳制,您可以在 Unity 项目中通过转到 Project Settings → Player → Other Settings → Clamp Blendshapes (Deprecated) 来启用它。这在 VRChat 中已被启用。)
  • 修复此问题的正确方法是始终明确设置 Blendshape 值。
  • 糊弄式修复此问题的方法是设置空闲图层中的状态为 Write Defaults On