いかにしてアバターのハンドサインは動かなくなり、そして動かすことができるのか
結論
VRCSDKのサンプルにある「vrc_AvatarV3HandsLayer」は本来Gesture用であり、FXに転用するのには不向きです。かといってFX用の「vrc_AvatarV3FaceLayer」はあまりにも大味過ぎるので、
VRChat向けアバターの表情制御(FXレイヤー)には、有志のテンプレートを使いましょう。
※こういうの↓
用語集
Avatar Descriptor
正確にはVRC Avatar Descriptor。アバターのルートオブジェクトに、Animatorコンポーネントとセットで付いているもので、これでリップシンク,アイトラッキング,移動モーション等、アバター固有の各種設定をしていく。
Animator
ゲームオブジェクトに付くコンポーネントの1種。アバター的には基本、ルートオブジェクトに1個付いている。
Animator Controller (以下Controllerと称する)
一言で言うとFXレイヤーの正体。
Unity的にはAnimatorコンポーネントにセットすることで動かせるようになる、アニメーションの動作手順書みたいなもの。
Avatars3.0的には、Playable Layersに各種専用のControllerをセットすることでアバターの動きをカスタムするもの。
この中にレイヤーがあり、レイヤーの中にステートがあり、ステート毎にAnimationClipを設定する構造を取っている。
AnimationClip
一連のアニメーション動作が記述されたファイル。
Avatars3.0的には、アニメーションというより、1フレーム分だけ記述して状態を表すものとして使われる事が多い。
Playable Layers
Avatars3.0(現行のVRChatのアバター制御機構)において、アバターの動き全般をカスタムできる機能。動きの種類に応じてBase/Additive/Gesture/Action/FXの5種類と、特殊用途のSitting/TPose/IKPoseがある。
Write Defaults
前提として、アニメーション操作とは「オブジェクトの各種状態を毎フレーム書き換え続ける事」であり、アニメーションをしないステートに遷移したら、最後に書き換えた状態のままになる。Write Defaultsは、この「アニメーションしなくなった時」に初期値に戻って欲しい時にオンにするプロパティ。
しかし、ステート単位の設定でありながらその効果はController全体に及ぶほか、Unityのバグ紛いの仕様+Unityも想定していないVRChat特有のControllerの使い方(Playable Layers)により、VRChatでは全てオフにすることが推奨されている。
Humanoid (Rigとも)
アバターの動きのうち、いわゆるモーションにあたる部分。AnimationClip上ではAnimator.*** と表記される。
Transform
全てのゲームオブジェクトに必ず1つだけ付いている、コンポーネントの1種。スケールやHumanoid以外のゲームオブジェクトの移動操作がこれで制御される。
Avatar Mask
Controllerのレイヤー単位で、HumanoidやTransformのアニメーションを部分的にフィルターするためのファイル。
Unityが想定する使い方としては、例えば上半身だけ別アニメーションに上書きしたい場合でも、全身分のアニメーションが記述されたAnimationClipを使い回せるようにする為に使う。
vrc_AvatarV3HandsLayerの原罪
2022年8月30日のBuild 1229アップデートにて、FXのバグが修正され、最上段レイヤーのAvatar Maskが「正しく適用される」ようになりました。
これは2020年8月6日のAvatars3.0実装以来ずっと放置され続けていたバグで、VRChatの推奨通りに組んでもGestureでTransformアニメーションが動かない、というものでした。
しかしこれは同時に、FXを「正しく実装していない」多くの販売アバターや、それを改変したアバターの指が動かなくなるものでした。
では何故「正しくない」実装のアバターが多いのか?これは更に時を遡り、SDK2時代のアバターの作り方が関係しています。
SDK2時代、アバターギミックとしてカスタムして使えるのは左右ハンドサイン7+7種類と、エモート8種類(と各種移動モーション)のみでした。表情筋の事は想定されていなかったのです。
そこで我々は、ハンドサインと共に表情もアニメーションさせる事で、アバターに表情筋を実装できることを発見しました。
しかしこの文化を知ってか知らずか、のちにVRChatが実装したAvatars3.0では、同時に新規実装されたアクションメニュー(パイメニュー、ラジアルメニューとも)から表情を操作する方針のもので、サンプルのPlayable Layers用Controllerも、FX用に関しては簡素なものでした。
我々はSDK2時代のアバター資産を生かすべく、Gesture用…つまりハンドサインを動かすためのControllerを複製し、転用する事で、ハンドサインで表情を切り替えるテンプレートを手っ取り早く手に入れることにしました。最初にして最大の過ちです。
vrc_AvatarV3HandsLayerの現在
VRChatの"改善"により、当初は問題無かった「vrc_AvatarV3HandsLayer」の転用は、もはや罠だらけとなりました。最初に述べたように、FX用に最適なControllerのテンプレートを有志が作って公開してくれています。ナンモワカラン人ほど、それらを使う事をオススメします。
そうは言っても、どうしても「vrc_AvatarV3HandsLayer」ベースで作ってしまったFXがあり、それを改修する必要がある人もいるかと思います。ここからは、「vrc_AvatarV3HandsLayer」をFX用に転用するにあたって直すべき点を羅列していきます。
GestureとFXでControllerを分ける
まずGestureとFXに同じControllerをセットしてはいけません。もしそうなっているアバターがあったなら、ControllerをCtrl+Dで複製して、Gesture用とFX用に分けましょう。後述する適用すべきAvatar Maskが異なるため、共通化すると指が動かなくなったり、Transformアニメーションが動かなくなったりします。
当然AnimationClipも別々に用意し直しが必要です。
AnimationClipからHumanoidアニメーションを無くす
FX用のAnimationClipにはHumanoidアニメーションを含めないようにしましょう。他の条件との組み合わせによりますが、指が動かなくなります。
特に「proxy_hands_***」系AnimationClipがステートに残ったままになっているケースが多いので注意です。
なお、ステートのMotion欄がNoneだと、Write Defaultsオフの場合は他のレイヤーを巻き込んでアニメーションを止めるバグがあるため、何かしらAnimationClipをセットしておきましょう(キーフレーム無しの空アニメーションでOK)。
Avatar Maskを外す
GestureでTransformアニメーションをさせている場合のみ、FXの最上段には専用のAvatar Maskが必要です…が、そうでない(つまりほとんどの)場合は不要です。むしろ無駄に付いていると、今度はFXの方でTransformアニメーションが動かなくなります。
特に「vrc_AvatarV3HandsLayer」ベースの場合、そのままだと本来Gesture用のAvatar Maskが付いたままの状態であり、指が動かなくなる不具合を引き起こします。
Motion Timeのチェックを外す
2フレーム以上使うアニメーションで悪さをするので、基本全部のステートからMotion Timeのチェックを外しておくと良いでしょう。特に「vrc_AvatarV3HandsLayer2」の方は、Right HandレイヤーのIdle2ステートに入っているパラメーターが間違っています。
そもそもGestureRightWeight/GestureLeftWeightパラメーターは、ハンドサインがFistの時しか中間値を取りません(VRChatの仕様)。チェックを残すとしてもFistだけで十分です。
Write Defaultsについて
2020年10月30日のBuild 1007アップデートにて、Write Defaultsオンだとブレンドシェイプ3倍バグ、その他バグの温床になるとの判断から、VRChatはWrite DefaultsをオフでControllerを組む事を推奨すると共に、サンプルテンプレートも全てWrite Defaultsオフのものになりました。
この時もまあまあな混乱が起きましたが、現在ではFX用Controllerについては、Controller内の全てのステートがWrite Defaultsオンかオフ、どちらか一方に統一されていればよろしい、という事で落ち着いています。(混ざっている場合、そのController全体のWrite Defaults挙動が不安定になります)
また、Write Defaultsオフで使う場合は、常時デフォルトアニメーションを再生させるレイヤーを追加する事でWDオンと同等の挙動にする、という案があります。これはWrite Defaultsオンで使う場合でも、ブレンドシェイプ3倍バグの対策になるので、Write Defaultsの有無に関係無く対策しておくと良いでしょう。
2023年11月21追記
2023年11月17日のBuild 1376アップデートにて、GestureとFXの両方がWrite Defaultsオンだと、VRC Stationに"座った"時にアバタースケールが倍化するバグが発生しました。
FX以外のControllerについては、Write Defaultsをオンにする理由は無いはずなので、基本的に全てWrite Defaultsオフで組んでおく方が安全です。
VRChat公式もWrite Defaultsは全部オフで統一する事を推奨しています。
そもそもPlayable Layersとは、どのようにしてアバターを動かすのか
ドキュメントを要約すると、Avatars3.0が出た当初と言ってること自体はほぼ変わっていなくて、「Humanoid操作はFX以外でやれ」「Transform操作はGestureでやれ」「HumanoidとTransform以外の一切はFXでやれ」「それぞれのControllerの最上段のAvatar Maskは特殊な評価に使っている」という事が書かれています。
Unityでは、アバターを動かすためのAnimatorには一つのControllerしかセットできません。そこでVRChatは、機能別に分けたPlayable Layersの各Controllerを、アバター読み込み時に"合体"させてAnimatorにセットしています。このUnityもびっくりの実装を達成するために、それぞれのControllerの最上段レイヤーにあるAvatar Maskを、Controller単位でマスクするために使うようになっています。これにより、より上段にあるControllerのアニメーションを"虚無"で上書きしないようにしている訳です。
Gestureはデフォルトでは手指を動かすControllerなので、サンプルでも両手だけ有効にされたAvatar Maskが最上段レイヤーにセットされています。
ActionはBase/Additive/Gestureの全てを上書きさせるのが目的のControllerなので、逆にAvatar Maskは不要で、代わりに必要無い時はレイヤーのweightを0にする形でマスクしています。
さて問題のFXですが、これも最上段レイヤーにAvatar Maskがある場合、それがFX全体のマスクとして利用されます。無い場合は、全てのHumanoidを無効かつ全てのTransformを有効にしたAvatar Maskが代替で割り当てられます。
アバターの指が動かない問題は、この手指Humanoidだけ有効になっているAvatar MaskがFXの最上段に来てしまうがために、Gestureのハンドサインアニメーションを"虚無"で上書きしてしまっていたのが元凶だった訳です。
なお、FXのWrite Defaultsがオン構成の場合はAvatar Maskの挙動が逆転し、FXにHumanoidアニメーションが存在すると、そのアニメーション分についてはFXのみで完結(Gesture以前のアニメーションを無視)しているかのような挙動を取ります。FXにHumanoidアニメーションを存在させてはいけない理由がこれです。
話を戻して、何故FXのデフォルトAvatar Maskは全部のTransformが有効なのかは、公式ドキュメントによると、そのTransformのゲームオブジェクトに付いている他のコンポーネントごとマスクしてしまわないため、だそうです。(実際には、Avatar Maskとは関係無く動いているように見えますが…)
ところで、TransformアニメーションはGestureでやる事になっていたはずですね。これも公式ドキュメントによると、Gestureではアニメーションが必要なTrnasformを有効にするAvatarMaskを、 FXではそのTransformのみを無効にするAvatarMaskを、それぞれ作る必要がある…とあります。
…ここでUnity標準のAvatar Mask生成機能を見てみると、一つのFBXに含まれるTransformしか追加できません。これではHierarchyに置いて色々追加改変したオブジェクトのTransformアニメーションができません!
という事なので、VRChatの推奨には叛逆しますが、(Humanoidでない)TransformアニメーションはFXに入れてしまい、FXからは全てのAvatar Maskを外す運用が、現状のオススメです。