写入默认 (Write Defaults)
文章原址:原文出处:https://notes.sleightly.dev/write-defaults/
写入默认 (Write Defaults)
Write Defaults 是 Animator States 中的一个选项,对于许多 Avatar 创作者来说,它可能会造成困扰,因为其行为有时非常奇怪和出乎意料。预期的行为如下:
Write Defaults
是动画状态(Animator States)的一个可选项,这对许多虚拟形象创作者来说都是一个令人头疼的问题,因为它的行为表现比较反直觉。其预期行为如下:选项决定了通过这个动画所做的更改是否保持不变。
译者注释:Write Defaults
决定动画中所做的更改是否是持久性的。选项决定了当前播放的动画对物体所做的更改是否在当前动画结束和离开状态后保持不变。
如果启用了 Write Defaults
选项,动画属性在离开 Animator 状态时将返回到默认状态。
译者注释:默认状态指的是当 Avatar 在上传时,一个物体所处的状态。比如一个方块在上传时的缩放是 (1 | 1.5 | 2),则模型在离开上一个动画状态后,在当前动画状态绘制前写回上个动画状态中动画属性的默认状态,不保留上个状态的更改(见示例)。并且是启用的,那么这个方块的默认状态就是缩放 (1 | 1.5 | 2) 并且启用。
如果禁用了 Write Defaults
,则不会写回默认状态,保留上个状态的更改(见示例)。选项,更改将保持不变。
译者注释:如果禁用了 Write Defaults 选项,当前播放的动画对物体所做的更改将保留下来。
默认情况下,Unity 会在新创建的状态上启用在新创建的状态上启用 Write
Defaults,Defaults,但 VRChat 提供的示例动画控制器(提供的默认 Animator Controller)没有启用Controllers 中是关闭 Write Defaults
了。 的。
默认新创建的动画状态为开启新建状态默认启用 Write
Defaults。Defaults。
示例:举例:
如果您有一个在层级( Hierarchy )中被禁用(即默认情况下关闭)的帽子(hat)如果你在上传时将帽子禁用(即默认关闭),并且您有一个看起来像这样的层级:如下所示:
在启用 Write Defaults
的情况下下:
- 当切换到
Hat On
时,帽子会被打开 - 当切换回
Empty State
状态时,帽子会被关闭(因为帽子被写回了默认状态)
在禁用 Write Defaults
的情况下:
当进入当切换到Hat On
时,帽子会被打开的状态时,帽子会切换为开启状态当回到 Hat Off (当切换到Empty
时,帽子会保持开启状态(因为没有动画将其关闭,也没有写回默认状态)State)的状态时,帽子会切换为关闭状态(因为这是默认状态)State
使用指南
在在使用 Write Defaults Off
的情况下: 时,请遵循以下几条规则。为了规整起见,我会在稍后作出解释:
当进入不要在一个控制器中混合使用HatWriteOnDefaults。混合使用的状态时,帽子会切换为开启状态Write 当进入DefaultsHat会使其表现得像Off (Empty State)的状态时,帽子将保持开启状态(因为您没有特意将其切换回关闭状态或写回默认值)
操作规则
在使用 Write Defaults Off
时,请遵循以下几条规则。我将在下方解释原因(仅为完整性起见):
请勿在单个控制器中混合使用Write Defaults。如此设置的表现将类似于使用Write Defaults Off。此条有例外情况:具有单个状态(或包含唯一的例外是只有单个状态的动画层。这些层可以使用,并且在 Direct Blend Trees
的单个状态)的层可以被设置为的情况下,应该设置为Write Defaults On。
-
这样做没问题是因为只有一个状态,不会受到 Write Defaults On
。的影响。 由于上面的层永远不会离开当前状态,所以您可以这样做,我们从不依赖
Write Defaults On行为。
不要将 Direct Blend Trees 的状态上上使用设置为 Write Defaults Off。
如果你使用 Write Defaults Off,你的所有状态里都应该包含一个填充动画或一个 Blend Tree。这个动画可以是空的,但通常建议使用一个不存在的物体属性,并且有至少两帧(有时候会将这种填充动画称为 Buffer)。
注意,使用 Write Defaults Off
WriteTransform Defaults进行动画处理会覆盖所有其他播放的动画控制器中动画化的 Off
Write Defaults Off
有关遮罩的更多信息,请参阅“Avatar注意:如果你由于 Masks”页面。
请注意:如果您因Off Transform 的动画而必须在 Gesture 和 FX 层中的层中使用
Transform(无论在有 WriteAvatar DefaultsMask,你只能用动画修改第一个材质球而不能修改其他的,因为被遮罩的 Off变换动画而必须使用遮罩,则不能在除第一个材质插槽之外的任何插槽上使用材质切换动画,因为无论遮罩是否启用,被遮罩的变换(无论是启用还是禁用)都不能在除第一个材质插槽之外的其他材质插槽上具有材质切换动画。Avatar Mask 的情况下 WD 是启用还是禁用)不能用动画修改除了第一个之外的材质球。
VRLabs 的 Avatar 3.0 Manager 是用于检查您是否违背了以上规则的实用工具(检测至少前两条规则) 可以帮助你检查你是否违反了以上规则(至少能检查第一条和第三条)。在该工具的 Write Defaults
选项卡中,它会告诉您是否混合使用了它会告诉你是否混用了 Write
Defaults,并会在您按下相应按钮时为您自动设置。Defaults,并帮助你统一设置。请注意,它不会在设置过程中特意排除它不会把 Direct Blend Trees,因此包含它们的动画状态必须在其名称中包含(WDTrees On)字段,以使该工具将其标记为当作例外,所以任何刻意设置为 Write Defaults On
。 的状态都必须在状态名称中添加 (WD On) 来标记为启用 Write Defaults。
解释上述规则的解释
不要在单个控制器中混合使用不要在一个控制器中混合使用 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 TreesTree 中,最终的权重会乘以一个因子最终权重会被一个 x/(1-yx)
, 的因子所乘,其中 x 是当前子级的权重,是当前子项的权重,y 是其他子级的权重之和,除以当前子级的权重。请注意,是其他子项的权重之和,除以当前子项的权重。注意,如果这个分数的分母为 0 或更低,则数值变为无穷大且永远不会停止增加。或更小,值会趋向于无穷大并不断增加。这意味着,如果您有如果你有 n 个子级,并将每个子级的权重设置为个子项,并且将每个子项的权重设置为 1/n,则最终结果是乘数为那么最终结果是乘数为 11,因此这允许你使用禁用 ,因此这允许您使用 Write Defaults
的 Direct Blend Trees。然而, Off这并不意味着这样做就是明智的。因此由于这会影响其他混合树和表现出其他奇怪的行为,您可以使用这并不意味着这是个值得推荐的做法,因为这会影响其他 Blend Trees 和导致其他奇怪的结果。启用 Write Defaults
On ,它更为简单。会更简单。
如果您正在使用如果你使用 Write Defaults Off,所有状态都应该包含一个动画或一个 Blend Tree
如果一个 Write Defaults Off,则您的所有状态都应包含一个动画切片或 Blend Tree。的状态没有包含动画,它可能会用之前动画层中的状态的动画默认值覆盖之前层中的动画。
不包含任何动画片段的 Write Defaults Off状态将会使用上一个状态中动画片段的属性默认值,覆写上方图层中的动画片段。
优点/缺点
Write Default On
优点:优点:
由于可以使用空动画状态更加简单,因为可以使用空状态/(或Bufferbuffer clip) 来恢复到上传时模型状态,因此使用稍简单些状态,这会让物体回到上传时的初始状态。允许在在不覆盖 Gesture 层动画内容的情况下在 FX层上使用变换动画,且不会将动画覆写到层使用GestureTransform层动画。在基础的双状态开关切换中,相对在基本的2 状态切换中,相比于 Write Defaults
Off,帧时间减少了Off减少了33%的帧时间(在Unity33%(仅在2019中)Unity 2019)。更容易更改默认值(如果您依赖上传时状态)可以轻松地修改更改状态(如果你依赖于上传时的默认状态的话)。
译者注释:另一种确定默认状态的方法是在之前的动画层中用动画锁定一个默认状态。
缺点:
依赖上传时状态依赖上传时的状态通常在混合使用在混合使用Write Defaults
时会出现问题时通常会出现问题不允许在不使用在不使用 ParameterDriversDriver或或者 AAP的情况下进行顺序迭代操作的情况下无法使用序列操作
译者注释:序列操作指的是将一段复杂的动画拆解成多个动画依次执行,这样将极大地减轻单个动画的复杂度以及减少维护和修改的难度。例如,将一扇有门把手的门打开再关上可以拆解成四个部分:1. 把手下压 2. 门打开 3. 把手松开 4. 门关上。
Write Default Off
优点:
不依赖于上传时状态不依赖于上传时的状态通常与混合使用通常可以混合使用Write Defaults
兼容且不会有问题允许顺序迭代操作可以使用序列操作
缺点:
在空状态中需要缓冲动画在空状态中需要有填充动画在没有遮罩的情况下对变换进行动画处理时,会覆盖所有手势变换在没有遮罩的情况下用动画修改对 Transform 时,会覆盖 Gesture 层的所有 Transform。在基础的双状态开关切换中,相对在基本的2 状态切换中,相比于 Write Default ON,帧时间增加了50%(仅在 Unity 2019)。
创作者指南
这些指南适用于创建应同时兼容 Write Defaults On 增加了50%的帧时间(在和 UnityWrite 2019中)Defaults Off 的预制件:
- 确保每个动画层只对一组属性进行动画(例如,每个状态应对相同的一组属性进行动画)。
- 如果需要在多个层中对同一属性进行动画,确保每个状态中都有动画,并注意较低层会覆盖较高层,始终在顶部保留一个 Reset 层作为默认状态。
创作指南
如果遵循本文中概述的指南,每个属性都会被动画化,你的动画系统将可以兼容
当创建应与 Write Defaults On
和 Write Defaults Off。
Blendshape 值翻三倍
在非常特定的条件下,当依赖于 Write Defaults On 时,Blendshape 的值会增加三倍。
(例如:你有一个空的 Write Defaults On 状态,它会过渡到一个 Blendshape 动画的 Write Defaults On 状态。在空的 Write Defaults On 状态中,动画 Blendshape 的默认值会被乘以 3。)
这个问题比其他问题更复杂和不明确,因此请将本文和以下内容视为观察结果,而非事实:
- 这个问题似乎是由 Additive 动画层的 Write Defaults Off
兼容的预制件时,这些指南将非常有用:请确保每个图层中都包含一组其专有,不同于其他图层所拥有的动画属性(例如,图层中的每个状态都应动画化相同的一组属性)。引起的。如果需要在多个图层上动画化同一属性,请确保每个状态都包含一个动画片段,且较低图层会覆写较高图层,并始终在顶部提供一个具有默认状态的“重置”图层。如果有一个仅包含
如果您遵循本文档中概述的指南,每个属性都将始终动画化,并且您的系统将始终与DefaultsOff 状态(如 VRC 提供的默认动画器)的 Gesture 动画层,这个现象就不会发生。但如果有一个正在播放的 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 引起的。问题会再次出现。它被一个只有这个问题与WriteAvatarDefaultsMaskOff状态(如默认状态)的手势层所阻止。播放一个使用Write Defaults On的状态会导致它再次发生。和动画是否实际可达到无关,只要它们存在于动画层上就会引发问题。它与任何遮罩和实际可过渡到的动画都无关。只需存在于图层上就足够了。只要您使用如果只使用 0或和 100 的值,就不会发生这个问题,它不会影响行为,因为0 乘0.3=0且和100 乘100.3=100 (由100(这是由于 Blendshape钳制导致的,您可以在Camping,你可以在你的 Unity项目中通过转到编辑器中启用这一选项,方法是前往 Project Settings → Player → Other Settings → ClampBlendshapes (Deprecated) 来启用它。这个功能在Blendshapes(已弃用)。 VRChat中已被启用。)启用了此选项)。修复此问题的正确方法是始终明确设置解决这个问题的正确方法是有一个动画始终明确地对 Blendshape值。值进行动画处理。糊弄式修复此问题的方法是设置空闲图层中的状态为一种快捷且不太完善的解决方法是将空闲层中的状态设置为Write Defaults
On。On。