其他 Avatar 相关知识
章节转载自 https://notes.sleightly.dev 的多个页面
本译文封面图标来自Flaticon
译者前文
- 本书由 LIII Works 你亲爱的酒保K 完成后续翻译以及由 VRCD Cocoa 及 SKP 起草。
- 本书翻译自 VRCLibrary 的 Miscellaneous Avatar Knowledge
- 本书翻译工作截止于2024年9月5日下午18点41分。
本书在译者监督下由人工智能翻译并由译者根据自身知识审阅和调整,翻译可能出现错误,如有疑问,请参阅原文 Miscellaneous Avatar Knowledge
写入默认 (Write Defaults)
原文出处:https://notes.sleightly.dev/write-defaults/
写入默认 (Write Defaults)
Write Defaults 是 Animator States 中的一个选项,对于许多 Avatar 创作者来说,它可能会造成困扰,因为其行为有时非常奇怪和出乎意料。预期的行为如下:
Write Defaults 选项决定了通过这个动画所做的更改是否保持不变。
译者注释:Write Defaults 选项决定了当前播放的动画对物体所做的更改是否在当前动画结束和离开状态后保持不变。
如果启用了 Write Defaults 选项,动画属性在离开 Animator 状态时将返回到默认状态。
译者注释:默认状态指的是当 Avatar 在上传时,一个物体所处的状态。比如一个方块在上传时的缩放是 (1 | 1.5 | 2),并且是启用的,那么这个方块的默认状态就是缩放 (1 | 1.5 | 2) 并且启用。
如果禁用了 Write Defaults 选项,更改将保持不变。
译者注释:如果禁用了 Write Defaults 选项,当前播放的动画对物体所做的更改将保留下来。
默认情况下,Unity 在新创建的状态上会启用 Write Defaults,但 VRChat 提供的默认 Animator Controllers 中是关闭 Write Defaults 的。
新建状态默认启用 Write Defaults。
举例:
如果你在上传时将帽子关闭(即帽子的默认状态是关闭),如下所示:
在启用 Write Defaults
的情况下下:
- 当切换到
Hat On
时,帽子会被打开 - 当切换回
Empty State
状态时,帽子会被关闭(因为帽子被写回了默认状态)
在禁用 Write Defaults
的情况下:
- 当切换到
Hat On
时,帽子会被打开 - 当切换到
Empty State
时,帽子会保持开启状态(因为没有动画将其关闭,也没有写回默认状态)
使用指南
在使用 Write Defaults Off 时,请遵循以下几条规则。为了规整起见,我会在稍后作出解释:
- 不要在同一个控制器中混合使用 Write Defaults。混合使用 Write Defaults 可能使其动画表现得像 Write Defaults Off。
-
-
唯一的例外是只有单个状态的动画层。这些层可以使用任意 Write Defaults ON 或者 OFF,并且如果这是一个 Direct Blend Trees 的话,更应该设置为 Write Defaults On。
-
这样做不会出问题是因为这个动画层只有一个状态,不会受到 Write Defaults On 的影响。
-
-
-
不要将 Direct Blend Trees 设置为 Write Defaults Off。
-
如果你使用 Write Defaults Off,你的所有状态里都应该包含一个填充动画或一个 Blend Tree。这个填充动画可以是空的,但通常建议使用一个不存在的物体属性,并且有至少两帧(有时候会将这种填充动画称为 Buffer)。
-
注意,使用 Write Defaults Off 对 Transform 进行动画处理会覆盖所有其他播放的动画控制器中动画化的 Transform。这特别意味着,对于 VRChat,如果你在 FX Layer 中用动画控制任何 Transform,它将覆盖 Gesture layer 中的所有 Transform,除非你设置一个 Avatar Mask,只启用被动画控制的 Transforms 并禁用所有其他 Transforms,并将这个遮罩应用到你的 FX Layer 动画层。有关 Avatar Mask 的更多信息,请参见 Avatar Masks 页面。
译者注释:建议使用一个不存在的物体属性,并且有至少两帧的原因是一个空动画的播放时长大约是1秒,而具有空属性2帧的动画大约是0.0167秒 (如果你没有修改过动画的采样率)
注意:如果你因为需要使用 WD Off 的修改 Transform 的动画从而必须在 Gesture 和 FX 层中使用 Avatar Mask 的话,你只能用动画修改被遮罩影响的 Mesh 的第一个材质球而不能修改其他的,因为被遮罩影响的 Mesh(无论在有 Avatar Mask 的情况下 WD 是启用还是禁用)不能用动画修改除了第一个之外的材质球。
VRLabs 的 Avatar 3.0 Manager 可以帮助你检查你的设计是否违反了以上规则(至少能检查第一条和第三条)。在该工具的 Write Defaults 选项卡中,它会告诉你是否混用了 Write Defaults,并帮助你统一设置。请注意,它不会把 Direct Blend Trees 当作例外,所以任何刻意设置为 Write Defaults On 的状态都必须在状态名称中添加 (WD On)
来标记为启用 Write Defaults 从而让工具不要修改它的 Write Default 状态。
上述规则的解释
不要在一个控制器中混合使用 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。
为了更清楚地说明这种乘法行为,对结果来说,在禁用 Write Defaults 的 Blend Tree 中,最终权重会被一个 x/(1-yx) 的因子所乘,其中 x 是当前子项的权重,y 是其他子项的权重之和,除以当前子项的权重。注意,如果这个分数的分母为 0 或更小,值会趋向于无穷大并不断增加。这意味着,如果你有 n 个子项,并且将每个子项的权重设置为 1/n,那么最终结果是乘数为 1,因此这允许你使用禁用 Write Defaults 的 Direct Blend Trees。然而,这并不意味着这是个值得推荐的做法,因为这会影响其他 Blend Trees 和导致其他奇怪的结果。启用 Write Defaults 会让一切都更简单可控。
如果你使用 Write Defaults Off,所有状态都应该包含一个动画或一个 Blend Tree
如果一个 Write Defaults Off 的状态没有包含动画,它可能会用之前动画层中的状态的动画默认值覆盖之前层中的动画。
优点/缺点
Write Default On
优点:
- 更加简单,因为可以使用空状态/ Buffer 状态,这会让物体回到上传时的初始状态。
- 可以在不覆盖 Gesture 层动画内容的情况下在 FX 层使用 Transform 动画。
- 在基本的 2 状态切换中,相比于 Write Defaults Off,帧时间消耗少 33%(仅在 Unity 2019)。
- 可以轻松地修改更改默认状态(如果你依赖于上传时的默认状态的话)。
译者注释:另一种控制默认状态的方法是在之前的动画层中用动画锁定一个默认状态,这对 Write Default On 有效,也是在 Write Default Off 情况下实现 Write Default On 的还原效果的办法,在稍后的创作者指南部分你会看到类似的内容。
缺点:
- 依赖于上传时的状态
- 在混合使用
Write Defaults
时通常会出现问题 - 在不使用 Parameter Driver 或者 AAP 的情况下无法使用序列操作
译者注释:序列操作指的是将一段复杂的动画拆解成多个动画依次执行,这样将极大地减轻单个动画的复杂度以及减少维护和修改的难度。例如,将一扇有门把手的门打开再关上可
以拆解成四个部分:1. 门把手下压 2. 门打开 3. 门把手松开 4. 门关上。
Write Default Off
优点:
- 不依赖于上传时的状态
- 通常可以混合使用
Write Defaults
且不会受到影响 - 可以使用序列操作
缺点:
- 在空状态中需要有填充动画
- 在没有 Avatar Mask 的情况下用动画修改 Transform 时,会覆盖 Gesture 层的所有 Transform 动画。
- 在基本的 2 状态切换中,相比于 Write Default ON,帧时间消耗多50%(仅在 Unity 2019)。
创作者指南
这些指南适用于制作应同时兼容 Write Defaults On 和 Write 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 引起的。
- 如果有一个仅包含 Write Defaults Off 状态(如 VRC 提供的默认动画器)的 Gesture 动画层,这个现象就不会发生。但如果有一个正在播放的 Write Defaults On 状态,问题会再次出现。
- 这个问题与 Avatar Mask 和动画是否实际可达到无关,只要它们存在于动画层上就会引发问题。
- 如果只使用 0 和 100 的值,它不会影响行为,因为 0.3=0 和 100.3=100(这是由于 Blendshape Camping,你可以在你的 Unity 编辑器中启用这一选项,方法是前往 Project Settings → Player → Other Settings → Clamp Blendshapes(已弃用)。 VRChat 启用了此选项)。
- 解决这个问题的正确方法是有一个动画始终明确地对 Blendshape 值进行动画处理。
- 一种快捷且不太完善的解决方法是将空闲层中的状态设置为 Write Defaults On。
人形遮罩 (Avatar Mask)
原始页面:https://notes.sleightly.dev/animator-masks/
Unity 行为
Avatar Mask 会基于在遮罩中启用和禁用的选项,阻止或允许 Humanoid Muscle 数值、材质球替换和 Transform 的动画处理。如果一个动画层具有一个启用了特定值的 Avatar Mask,那么该层的动画可以对该值进行动画处理。如果一个动画层具有一个禁用了特定值的 Avatar Mask,那么该层的动画则不能对该值进行动画处理。具体而言:
- 如果一个动画层具有启用了 Humanoid Muscle 数值(例如左手)的 Avatar Mask,那么该层中的动画可以修改该 Humanoid Muscle 数值。
- 如果一个动画层具有禁用了 Humanoid Muscle 数值(例如左手)的 Avatar Mask,那么该层中的动画不能修改该 Humanoid Muscle 数值。
- 如果一个动画层具有启用了或未指定的 Transform 的 Avatar Mask,那么该 Transform 可以通过该层的动画修改其位置、旋转和缩放,以及对第一个材质球进行替换。
- 果一个动画层具有禁用了 Transform 的 Avatar Mask,那么该 Transform 的位置、旋转或缩放,以及第一个材质球的替换,都不能通过该层的动画进行修改。
- 如果一个动画层有任何 Avatar Mask,它不能对任何材质球的替换(除了第一个材质球)或控制 Animator 上的根 Transform。
其他内容(如 blendshapes 和任何其他组件)不会受到 Avatar Mask 的影响。
设置 Avatar Mask 的原因在于,如果你在一个层中控制一个 Humanoid Muscle 数值,然后在另一个层中控制同一个 Humanoid Muscle 数值,(无论是在 Animator 中更低的动画层还是在不同的 Playable Layers 中),前者的动画会被后者覆盖(除非另一个层是 Additive 层,在这种情况下,它会叠加在前者之上)。
对于 Transform,这种情况仅在第二个动画使用 WD off 并且位于一个稍后应用的 Playable Layer 时发生。
例如,如果没有 Avatar Mask,如果你在 Gesture Layer 中用动画控制手部动作,而在 FX Layer 中使用了不同的动画控制面部表情(同时也控制了 Humanoid Muscle),那么手部的值将被 FX Layer 覆盖。
注意:这意味着,如果你有一个 Humanoid 动画,没有进行适当的 Avatar Mask 以启用所需的 Humanoid Muscle 数值并禁用其他数值的情况下,所有其他 Humanoid Muscle 数值将会被覆盖。
这也意味着,如果你在 Gesture Layer 中有 Transform 动画,而在 FX Layer 中有一个未被遮罩应下的 WD Off 的控制 Transform 的动画,所有 Gesture Layer 中的 Transform 动画都会被覆盖。
默认的 VRChat FX Layer 使用了未被遮罩影响的 WD off 的混合树。如果你使用 VRChat 默认的 FX Layer,这可能导致在 VRChat 中 Transform 动画无法播放。如果你想在 Gesture Layer 中使用控制 Transform 的动画,你必须使用你自己的 FX Layer。
VRChat Playable Layers 行为
所有 Playable Layers 会依次播放。首先是 Base 层,然后是 Additive 层,接着是 Gesture 层,然后是 Action 层,最后是 FX 层。
在前四个层(Base、Additive、Gesture 和 Action)中,你应该只使用影响 Transform(无论是 Humanoid Muscle 还是 Transform 动画)和开关 GameObject 的动画。
这不是因为 Avatar Mask,而是因为这四个层只在你的本地 Avatar 克隆体上播放,而不会在你的镜像和阴影克隆体上播放。VRChat 复制本地 Avatar 上每个物体的 Transform 和开关状态,并将它们应用到 Avatar 的镜像和阴影克隆体上。然而,VRChat 不会复制除了 Transform 和每个 GameObject 的开关状态之外的任何内容,这意味着如果你的动画控制了其他内容,如 blendshapes、材质球替换或着色器设置,VRChat 不会将这些属性复制到镜像和阴影克隆体上。克隆体会播放自己的 FX Layer,这就是为什么除了 Transform 和物体的开关状态之外的一切都应该在 FX Layer 中控制的原因。
例如:如果你在 Base Layer 中进行材质球替换,它不会在镜像和阴影克隆体上生效。
本文仅详细讨论了 Avatar Mask 和行为。如果你想了解更多关于 VRChat 层的内容或 VRChat 推荐的层使用方法,你可以在以下页面找到更多信息:
Playable Layers | VRChat Creation
基本动画层
Base
Base 该层应仅动画处理 Transform(无论是直接还是通过 Humanoid Muscle)和/或物体的开关状态。
VRChat 推荐将此层用于运动等只控制 Humanoid Muscle 的动画。
Additive
Additive 该层应仅使用控制 Transform 的动画和/或控制物体开关状态的动画。它是以叠加混合的方式进行的,这意味着任何动画不会替换基础层的动画,而是将值叠加。
VRChat 推荐将此层用于运动的调整,如呼吸效果,并且只应该使用控制 Humanoid Muscle 的动画。
Gesture
该层应当只使用控制 Transform 和/或物体的开关状态的动画。Gesture 有一些特殊的性质,即 VRChat 会将 Gesture 的第一个动画层的 Avatar Mask 应用到其下所有的动画层上,如果在第一层的 Avatar Mask 或某一层的 Avatar Mask 中禁用了动画控制(无论是 Humanoid 还是 Transform),它就无法被动画控制。
因此,如果你想使用任何控制 Humanoid Muscle 的动画,你必须制作一个专门允许这些 Humanoid Muscle 的 Avatar Mask 并将其放在第一层中。
如果你想你想使用任何 WD Off 的控制 Transform 的动画,你必须制作一个专门允许这些 Transform 并禁用其他部分的 Avatar Mask,并将其放在第一层中。
VRChat 推荐将此层用于控制 Transform 和仅影响特定身体部位的 Humanoid 动画。
Action
该层应仅使用控制 Transform 和/或物体的开关状态的动画。Action 在默认情况下的权重为零。在你在 Action 层中进行任何操作之前,你需要使用 Playable Layer Control State Behavior 将该层的权重混合到一个有效数值,然后再过渡到你要执行的实际操作。当你完成后,确保将其权重调整回零,否则其他层的动画将会全部被覆盖。
VRChat 推荐将此层用于覆盖前面层中的任何 Humanoid 动画,例如动作表情或 AFK 动画。
FX
由于该层会在所有克隆体上运行,因此这是你可以运行任何动画的地方。请注意,你仍然可以在这一层控制 Transform,只要设定了适当的 Avatar Mask。
如果第一个动画层没有设定 Avatar Mask,它将创建一个默认的 Avatar Mask,禁用所有 Humanoid Muscle 数值和启用所有 Transform,并将其应用到所有层上,使其在这个 Avatar Mask 或层的 Avatar Mask 中禁用的内容会被禁用。
如果第一个动画层中使用了任何 Avatar Mask,第一层的 Avatar Mask 也会应用到所有层。
因此,如果你想在 FX 控制 Humanoid Muscle,你必须制作一个专门允许你想控制的 Humaniod Muscle 的 Avatar Mask 并将其放在最顶层。如果你不关闭不需要的 Humaniod Muscle,Gesture 中的动画内容就会全部被覆盖。
如果你使用 WD off,同样的逻辑也适用于 Transform。
VRChat 的默认 FX 层有一个混合树,Write Default 为 Off,这可能会使得一些 Transform 动画出问题。如果你想在任何其他 Playable Layers 中使用 Transform 动画,请不要使用默认的 FX 层。
VRChat 推荐将此层用于所有非 Transform 动画的内容,例如启用/禁用物体、组件、材质球替换、着色器动画、粒子系统动画等。
特殊层
T-pose:
T-Pose 用于确定 Avatar 的各种测量值,特别是视点(或视角球)的放置。它是独立的,因此 Avatar Mask 并不重要。
IK Pose:
IK Pose 用于确定主要关节的弯曲。在 IK 姿势中,你的关节应该略微弯曲,以符合其弯曲方向。它是独立的,因此 Avatar Mask 并不重要。
Sitting Pose:
这个控制器用于控制坐下时的姿势。当你坐下时,Avatar 的视点会用于校准。你可以创建一个“坐下”动画以及一个“坐着”的动画来让 Avatar 看起来像是坐下了。这一层类似 Action,会覆盖所有的 Humanoid 动画,以使角色坐下。
参数类型不一致 (Expression Parameter Mismatch)
原文出处:https://notes.sleightly.dev/parameter-mismatching/
译者注释:Bool 布尔 (True/False)
译者注释:Int 整数/整形 (0, 1, 2, 3, 4, 5...)
译者注释:Float 浮点/小数 (0.13, 0.45, 0.255...)
译者注释:动画器参数
指的是 Animator 内的参数;Expression 参数
指的是 VRC Expression Parameter List 内的参数
在一般的 VRChat Avatars 3.0 创作过程中,VRChat Expression Parameters 的参数类型应该设置为与 Animator 内相同的类型(Bool
、Int
、Float
)。
然而,Expression Parameters 和 Animator 参数之间的参数类型在不一致的情况下也仍能正常工作。这种行为因参数类型的不同而有所差异,具体如下所述。
一个标记为 Toggle
的参数被添加到 VRChat Expression Parameters 中,类型为 Bool
一个标记为 Toggle
的参数被添加到 local Animator 参数中,类型为 Float
已知互相兼容的参数类型及其行为
Expression Parameter Bool
动画器参数 → Expression 参数 | Expression Bool = False | Expression Bool = True |
Bool → Bool | Bool = False | Bool = True |
Bool → Int | Int = 0 | Int = 1 |
Bool → Float | Float = 0.0 | Float = 1.0 |
Expression Parameter Int
动画器参数 → Expression 参数 | 行为 |
Int → Bool | 任何大于 0 的 Int 值将使 bool 为 True |
Int → Int | 预期行为 |
Int → Float | 直接转换:例如 Int = 2 → Float = 2.0 |
Expression Parameter Float
动画器参数 → Expression 参数 | 行为 |
Float → Bool | 任何大于 0 的 Float 值将使 bool 为 True |
Float → Int | 四舍五入转换:≥0.5 → 1 ; <0.5 → 0 |
Float → Float | 预期行为 |
为什么 Avatar 参数类型之间互相兼容?
Unity Animators 在 C# 后端使用浮点数处理参数,而 VRChat 则使用 SBytes 代替 bool、int 或 float。
Animator 和 VRCSDK 通过允许你从界面中选择参数类型来优化用户体验。
如果这样来看的话,参数并不是被转换,而是不一致。
这种不一致的兼容性同样适用于 VRChat 的内置参数。
目前,AV3 Emulator 和 GestureManager 已经实现了模拟参数类型兼容的功能。
使用混合树来合并多个动画层
原文出处:https://notes.sleightly.dev/dbt-combining/
由于 Animator Controller 中 Animator Layers 对性能的影响较大,一个对性能更友好的做法是通过使用 Direct Blend Tree 将切换开关和转轮开关等功能合并到同一个 Animator Layer 中。
译者注释:转轮开关指的是一种圆形的轮盘菜单操作模式,通过类似进度条的菜单来控制一个数值从 0% - 100%
理解什么是 Direct Blend Trees
Direct Blend Trees 允许你为其内的每一个 Animation 或 Blend Tree 分支设置参数。这让你能够在同一个 Blend Tree 中同时控制多个动画。
译者注释:有时候 Direct Blend Trees 也被称为 DBT
对于 VRChat,我们可以利用这一特性,在单个 Direct Blend Tree 中制作多个切换开关和转轮开关,类似于在多个动画层中进行的操作。
Direct Blend Tree 的结构和功能与 Animator Controller 非常相似,因此将它们视作 Animator Controllers 可能会更容易理解。这是一种简化的理解 Direct Blend Trees 的方式,但需要注意的是,尽管它与 Animator Controllers 非常相似,但并不完全相同!
两者之间存在一些关键差异,这些差异在很大程度上限制了 Direct Blend Trees 的使用场景和实现方式。有关更多信息,请参阅“限制和已知问题”部分。
一个包含 3 个服装组件切换开关的 Direct Blend Tree
译者注释:
- Layer Weight:层级权重
- Parameters:参数
- Transitions:过度
- Animator Controller动画器
- Layers:层
- States:状态
创建切换开关和转轮开关
在 Direct Blend Tree 中制作切换开关和转轮开关与在 Animator Layer 中制作常规切换开关并无太大区别,也不会更为复杂。
步骤 1
- 创建一个新的 Animator Layer,然后在空白区域右键点击以创建一个新的 Blend Tree State。
- 将 Blend Tree State 的 Write Defaults 值设置为 ON!这是必要步骤!我们会在 Write Defaults 部分详细说明原因。
译者注释:无论你的其他动画层是否使用 Write Default,只要你的这个动画层只有这一个Direct Blend Tree并且只有这一个 State,在这样的情况下单独启用 Write Default 不会影响你的动画器,也不会造成任何问题,无需担心启用 Write Default会造成问题。
步骤 2
步骤 3
- 将一个新的 Blend Tree 作为子项添加到 Direct Blend Tree 中。
- 如果还没有,创建一个新的 float 参数(例如
Weight
),并将值设置为 1。
- 这个参数不是用于切换开关本身的参数,而是一个独立的参数,用于将子项的权重设置为 1,以便它能被完全控制,类似于你将 Animator Layer 的权重设置为 1。
- 这个参数不是用于切换开关本身的参数,而是一个独立的参数,用于将子项的权重设置为 1,以便它能被完全控制,类似于你将 Animator Layer 的权重设置为 1。
- 将子项的参数设置为这个 float 参数。
- 你可以为所有子项重复使用这个 float 参数,无需为每个子项创建新的参数。
- 确保 Direct Blend Tree 的
Normalized Blend Values
没有勾选。
步骤 4
- 选择子项 Blend Tree,确保 Blend Type 设置为
1D
。- 你可以在窗口顶端重命名 Blend Tree 以便于管理。
- 为你正在制作的切换开关或转轮开关创建一个新的 float 参数,并将其设置为当前子项 1D Blend Tree 的参数。
- 为该子项 1D Blend Tree 中添加两个新的动画,并放入你通常用于切换开关或 1D 转轮开关的动画。
- 如果你习惯使用 Motion Time 的单个动画来制作转轮开关,你需要将动画修改成成适合 1D Blend Tree 的转轮开关形式。
仅使用一个动画片段(如 WD On 工作流程中那样)是行不通的!你需要单独的动画或一个合并动画。
译者注释:合适 1D Blend Tree 的动画指的是,例如你的动画有4个帧,对应4套服装的开启,那么你需要将这4个帧做成4个独立的动画,每个动画控制一套服装的开启,这样才能分散在 1D Blend Tree 上。传统的 Motion Time 式做法不能在 Blend Tree 中直接套用。
步骤 5
- 将 1D Blend Tree 使用的参数添加到你的 VRChat Expression Parameters List 中。
- 如果你正在制作转轮开关,将类型设置为
float
。 - 如果你正在制作切换开关,将类型设置为
bool
。
- 由于 参数类型不一致 的行为,这样设定也可以正常工作。
- 如果你正在制作转轮开关,将类型设置为
译者注释:如果你的设计中具有多余2个状态,将不合适 参数类型不一致 的做法,你需另外设计一个合适的方法来驱动。
- 重复以上步骤来制作所有需要的切换开关和转轮开关,你可以这样制作任意数量的开关。
写入默认(Write Defaults)
在处理写入默认(Write Defaults)时,Direct Blend Trees 是一个例外。它的 Write Defaults 值可以和 Animator Controller 的其他部分的设定不同,这意味着你可以混合使用 Write Defaults,只要不在同一个动画层中混用即可。
对于 Direct Blend Trees 来说,即使 Animator Controller 的其他动画层使用 Write Defaults Off,我们也可以安全地使用 Write Defaults On。能够在 Direct Blend Trees 使用 Write Default On 可以帮助我们避免以下 Write Default Off 的 Blend Tree 具有的问题:
Write Defaults Off 的 Direct Blend Trees 的问题:
- 权重必须标准化
- 动画控制的属性值必须
- 使用多个 Blend Trees 时不稳定
- 输出结果会被"平滑化"
- 不能用动画作为第一分支
因此,不建议使用 Write Defaults Off 的 Direct Blend Trees,因为它们比 Write Defaults On 的版本更不稳定且更难以处理。即使 Animator Controller 的其他部分使用 Write Defaults Off,使用 Write Defaults On 的 Direct Blend Trees 也是完全安全的。
译者注释:无论你的其他动画层是否使用 Write Default,只要你的这个动画层只有这一个Direct Blend Tree并且只有这一个 State,在这样的情况下单独启用 Write Default 不会影响你的动画器,也不会造成任何问题,无需担心启用 Write Default会造成问题。
你可以在 Blend Tree 的名称前添加前缀(WD On),这样在使用 https://github.com/VRLabs/Avatars-3.0-Manager 批量设置 Animator Controllers 的 Write Defaults 值时不会受到影响。
这对于希望确保他们产品的用户在使用类似工具时不会意外关闭 Write Defaults 的 Avatar 和 Prefab 创作者特别有用。
将 Write Defaults 值从 On 更改为 Off 将会使得 Blend Tree 出错,直到 Write Defaults 被设置为 On!
嵌套 Direct Blend Trees
如果你有很多切换开关和转轮开关,你的 Direct Blend Tree 可能很快就会变得庞大且难以管理。你可以通过将 Direct Blend Trees 嵌套在一起,模拟文件夹的结构,从而提高组织性。
如果你在嵌套之前已经创建了所有的切换开关和转轮开关,你需要把他们全部删除,然后在文件夹里重新制作,因此最好预先考虑好这一点(除非你有工具可以重新排列 Blend Trees)。
译者注释:确实有一个美妙的工具可以重新排列 Blend Trees,但是纸张的空间太小了,就不在此多赘述了
如图所示,我们有一个包含九个子项的 Direct Blend Tree。我们可以通过利用更多的 Direct Blend Trees 将它们组织成文件夹。
首先,你想制作几个文件夹,就新建几个 Blend Tree,方法与创建切换开关或转轮开关时相同。
接下来,选择每个子项,并在检查器中将 Blend Type 更改为 Direct。
然后,按照前文所述的办法制作切换开关和转轮开关,只不过现在你是在文件夹内部制作。
为了更方便维护,你还可以选中文件夹,然后在检查器顶部重命名这些文件夹。
你可以给子文件夹设置和根 Direct Blend Tree 的相同 Weight 参数,如前文第3步所述。
有关将多个转轮开关和切换开关合并在一起的示例,请参见 Direct Blend Tree Radials and Toggles (Nested)。
你可以双击任何一个 Direct Blend Tree 来在一个独立窗口中打开它,这在你的 Blend Tree 规模巨大,以至于出现性能问题的时候尤其有用。
你可以通过点击左上角的箭头返回到完整的 Blend Tree 视图。
进阶 Blend Tree 技术
Blend Trees 的应用远不止简单的切换开关和转轮开关,还包括:
- 执行基本的数学运算,如加法、减法和乘法
- 解决数学方程,例如基本的指数平滑
- 模拟逻辑门,如 AND、OR 和 XOR 门
截至目前,这些技术相对缺乏详细文档,超出了本指南的范围。
如果需求足够大,未来可能会添加相关的扩展文章。
当前限制和已知问题
- 目前对于动画切换,如溶解切换以及 Motion Time 等没有令人满意的解决方案。
- 对于驱动其他参数,例如排他性切换需要使用 Parameter Driver,也没有令人满意的解决方案。
- 首次运行 Blend Tree 时,动画属性的值可能会在一帧内被设置为 0。
译者注释:排他性切换指的是,例如有3套服装,同时间只应该启用一个,而不是有2个或3个同时启动用。例如 Int 天然的具备排他性,但你不能直接在 Direct Blend Trees 中使用整数。一些特性需要设计额外的功能模块或者逻辑才能在 Direct Blend Trees 中使用。