VRChat 中利用 Animation Parameter 与 Expression Parameter 类型不一致(Parameter Mismatching)的理由
型の不一致 (Parameter Mismatching) を使う理由
前言
在Avatar机制中,Animation Parameter(以下简称AnimParam)与Expression Parameter(以下简称ExParam)有时会在Unity中被设置为不同的数据类型。这就是所谓的Parameter Mismatching(参数不匹配)。
本次将解释“为什么特意采用这种难以理解的设置”以及其意图是什么等积极理由。
同时,也会涉及那些常见的、关于“即使那样设置也没有问题地运行”的消极理由及相关事项。
此外,本次解说将以先前文章中介绍过的实现为例,因此建议先阅读那篇文章。
結論
为了节省Synced Bits。
这是显示在ExParam Inspector顶部的

内容。
当前的 VRChat 将同步参数的数据总量限制为 256bit。
Float 类型的 Synced Bits 为 8,Bool 类型的 Synced Bits 为 1。
因此,通过在 ExParam 中将其设置为 Bool 类型,可以削减多达 7 个 Synced Bits。
是不是因为出乎意料地微不足道的理由而感到松了一口气?
但这包含重要的思维整理。
也就是说,“将 ExParam 设为 Bool 类型并不是为了‘用于切换’”。
因为在 ExMenu 中,如果为切换(Toggle)的 Parameter 设置 Float 类型的参数,就可以指定 Float 类型的 1(所谓的 1.0f),

当切换处于 ON 时,会设置 Float 类型的 1;当切换处于 OFF 时,会设置 Float 类型的 0。
此外,根据 VRChat 官方的说法,远程同步的 Float 参数可以精确表示 -1、0、1 的值。1
因此,并非“如果不使用从 Bool 类型到 Float 类型的 Parameter Mismatching,就无法向 AnimParam 传递精确的 1.0f”
接下来,转入消极的理由及相关事项的说明
将 Float 参数作为 Bool 设置的理由
你可能会想:"本来应该是 Float 型的 AnimParam,能不能擅自用 ExParam 将其声明为 Bool 型呢?"
当 Bool 型的 ExParam 被设置为 true 时,同名且类型为 Float 的 AnimParam 会被设置为 Float 型的 1。
反之,当 ExParam 被设置为 false 时,AnimParam 会被设置为 Float 型的 0。
因此,即使 ExParam 被设置为 Bool 型,Float 型的 AnimParam 也会正确地接收到 Float 型的 0 或 1。
(关于其他类型的组合,请参阅 VRCSchool 的解说)
这对于熟悉编程的人来说,与所谓的“隐式类型转换”行为相同。但严格来说,它们并不完全相同。
在 Unity 的 UI 中可以看到 Bool、Int、Float,但在 VRChat 内部,它们都作为单一的 SByte 类型进行处理。
无论是 Bool、Int 还是 Float,在 VRChat 内部都是以 SByte 处理的,只发生了从 SByte 到 SByte 的转换,并没有进行“类型转换”。
看起来像是从 Float 到 Bool 进行了“隐式类型转换”,但这仅仅是在 Unity 的后端层面上发生的。2
顺便一提,根据 VRChat 官方说明,同步 Float 参数以 1/127 的精度同步 -1, ..., 0, ..., 1 的值。1
原本可以用 32bit 表示的 Float 只能取 -127/127, -126/127, ..., 127/127 这 255 种值,这与 SByte(有符号 8bit 整数)只能取 $2^8 = 256$ 种值是一致的。
为什么希望 AnimParam 只取 0 或 1 的值
“AnimParam 是 Float 类型,本来应该能取很宽范围的值,但进行这个设置后就不能取 0 或 1 以外的值了,这样没问题吗?”可能有人会这么想。
首先,由于 BlendTree“BoxCollider”是 1D BlendTree,因此会根据 Parameter“IsBoxCollider”的值来混合并播放附加的 Animation Clip。
为了理解 1D BlendTree,假设附加的 Animation Clip 如下所示:
| Animation Clip 名称 | "Attached side Threshold" | "Animation Clip 内容" |
|---|---|---|
| "Constant_Zero.anim" | 0 | "在整个 Animation Clip 中将某个属性设置为 0" |
| "Constant_One.anim" | 1 | "在整个 Animation Clip 中将某个属性设置为 1" |
此时,如下一张图片所示,当参数“IsBoxCollider”的值为0.3时

在红色条位置处蓝色部分的高度比例范围内,各个Animation Clip将被播放。准确地说,将播放如下加权平均后的值
\begin{aligned}
\text{実際に再生される値}
&= (1 -\text{IsBoxCollider})\times\text{Value}_\text{Constant_Zero}
+ \text{IsBoxCollider}\times\text{Value}_\text{Constant_One} \\
&= (1 - 0.3)\times 0 + 0.3\times 1 \\
&= 0.3
\end{aligned}
这被称为“混合/被混合”
当一个Animation Clip内的值随时间发生变化时
(例如使用SeatPosition_Backward2Forward.anim时)
通常加权平均的结果也会随时间变化,但
本次假设各Animation Clip中的值在整个过程中保持恒定,因此实际播放的值(加权平均结果)不依赖于时间
反过来,在本次使用的Animation Clip中,混合结果不依赖于时间
| Animation Clip名称 | 附加侧的阈值 | 动画剪辑的内容 |
|---|---|---|
| BoxCollider_Off | 0 | 在整个动画剪辑中,Box Collider 组件将关闭 |
| BoxCollider_On | 1 | 在整个动画剪辑中,Box Collider 组件将开启 |
在切换“显示椅子”的内部实现 BlendTree “BoxCollider” 中,我们希望 Box Collider 组件仅表示开启和关闭两种状态。
因此,参数“IsBoxCollider”应仅取两端的值,即“0 或 1”。
相反,我们不希望出现像 0.3 这样的“混合”值。
因此,Float 类型的 AnimParam 仅取 0 或 1 的值是理想的。
结论的支持
由于 ExParam 为 Bool 类型,可以节省 Synced Bits
通过将 ExParam 设为 Bool 类型,使其仅取 true 或 false 的值,
传递给 Float 类型的 AnimParam 的也仅为 1 或 0 的值,
因此不会发生混合,可以毫无问题地用作仅表示两种状态的“切换”。
结语
在那些平时利用“类型不匹配”的人中,是否也有人曾认为“因为用于切换 所以将 ExParam 设为 Bool 型”呢?
如果本文能帮助大家整理思路,我将不胜荣幸。
-
VRChat。“Animator Parameters”。VRChat。2026。 https://creators.vrchat.com/avatars/animator-parameters/#parameter-types, (2026-11-05) ↩ ↩2
-
Jellejurre、JustSleightly。“Expression Parameter Mismatching”。VRCSchool。2024。 https://vrc.school/docs/Other/Parameter-Mismatching/#ea79f2b19900472cb27828cb4b9d193c, (2026-11-05) ↩
来源:Qiita · Unity 开发社区 · qiita.com