[VRChat] コントローラーの握り具合に応じて表情を変える

VRChatではコントローラーの握り具合に応じてアバターのアニメーションを変化させることができます。
本記事では一例として、コントローラーの握り具合で表情を変化させる方法を説明します。
なお、本記事ではOculus Quest2を使用することを前提にしています。ですが、他のコントローラーを使用する場合でも参考になる内容かと思います。

目次

この記事の概要

本記事では、コントローラーの握り具合に応じて表情を変化させる方法に絞って説明します。
アニメーションに必要なAnimation ClipやAnimation Controllerの基礎的な説明はしませんので、こちらの概念がわからない場合は他の記事をご参照ください。また、VRCSDKの設定方法等も説明していませんので、わからない場合はそちらも別途お調べください。

表情を変化させるとは

具体例

以下の動画では真顔から笑顔へ顔を変化させています。コントローラーの握り具合により笑顔になるまでの速度を早めたり遅くしたりできます、変化の途中で表情を止めることもできます。

握り具合とは

握り具合というのは、以下の画像内で説明されている"Axis1D.PrimaryHandTrigge"という名前のトリガーの押し込み具合のことです。

f:id:yakumo890:20211119235618p:plain
Quest2のコントローラーの名称

(出典: https://developer.oculus.com/documentation/unity/unity-ovrinput/)

Quest2のコントローラーの場合はFistのハンドジェスチャーの握り方をしている場合のみ値を変化させられるようです(この情報は筆者がデバッガを使って確認しただけであり、公式情報ではありません) 。
Fistというのはグー(✊)の手のことで、コントローラーを以下のように握る事により表現できます。

f:id:yakumo890:20211119235621p:plain
Fistの握り方

この状態で、トリガーの押し込みを緩めたり強めたりすれば表情も変化させられます。

実現方法

仕組みの説明

はじめに仕組みから説明します。やり方だけ知りたい方は読み飛ばしても良いです。

このギミックの実現方法は、GestureRightWeight/GestureLeftWeightMotion Timeに設定するというものです。
これらの用語について説明します。

GestureRightWeight/GestureLeftWeightとは

GestureRightWeightとGestureLeftWeightは、VRChatがユーザー向けに用意しているAnimation Parameterの一つです。
これらの値は、ユーザーがコントローラーを握っている強さに応じて0から1までのいずれか実数値になります。GestureRightWeightは右手のコントローラーに対応し、GestureLeftWeightは左手のコントローラーに対応します。これらのパラメーターは左右以外に違いはないので、以下の説明ではこれらをまとめてGestureWeightと呼ぶことにします。
この値の変化はどのようにコントローラーを握っているかに依存するようで、前述の通りQuest2のコントローラーではFistの握り方をしているときのみトリガーの押し込み具合で変化させることができます。全く押し込まなければ0、最大まで押し込んでいれば1です。

Motion Timeとは

UnityのAnimation Controllerには、アニメーションの特定の割合だけ進んだ部分のみ再生するMotion Timeという仕組みがあります。
たとえば以下のような、キューブが60フレームでx軸方向に10動くアニメーションがあったとします。

このアニメーションに変更を加えていきます。
まずは、Animation Parameterを追加します。追加するパラメーターのタイプをFloatにし、名前を"Motion"にします。
つぎに、ステートの「Motion Time」の横にあるParameterにチェックをつけます。そうすると、プルダウンメニューが追加されますので、先程追加したMotionというパラメーターを設定します。

f:id:yakumo890:20211120003257p:plain
Motion Timeの設定

Motionを0.5に設定してアニメーションを再生します。そうすると、キューブがx軸方向に5だけ移動した位置で静止します。

f:id:yakumo890:20211120004039p:plain
キューブがX=5の位置に移動

この状態でMotionの値を変えると、それに応じてキューブが移動します。

これはMotionというパラメーターで指定した割合(0.5だったら50%)だけアニメーションが進んだ部分のみ再生しているからです。
この仕組は、ゲーム中に変化するパラメーターに応じてアニメーションの再生を変えたり、アニメーションの進行速度を別の要因と同期させたりするのに使えます。

そして、このMotion TimeによりGestureWeightの値とアニメーションを同期させることにより、コントローラーの握り具合に応じてアニメーションを変更させることができるようになります。

詳細な設定手順

表情を変化させるとはの表情変化を例に説明していきます。

1. 筆者の作業環境

  • OS: Windows 10 21H1
  • Unity: 2019.4.31f1

VRCSDKは3です。2でも実現することができるようですが本記事では説明しません。

2. 表情のアニメーションを作成する

表情のアニメーションには、2つのキーフレームを追加する必要があります。
1つ目のキーフレームはコントローラーを全く握っていないときの表情で、2つ目のキーフレームはコントローラーを最大まで握っているときの表情です。 この2つのキーフレームに以下の表情を割り当てます。

f:id:yakumo890:20211120223034p:plainf:id:yakumo890:20211120223037p:plain
右が1つ目のキーフレーム、左が2つ目のキーフレーム

これらのキーフレームの間隔ですが、1フレーム以上空いていれば構いません。今回の例では1フレーム空けています。

3. FXレイヤーで使用するAnimation Controllerを設定する

表情のアニメーションはFXレイヤーに入れなければなりません。なので、今回作成するアニメーションはFXレイヤー用のAnimation Controllerに入れます。

まず初めに、Animation Controllerに表情用のレイヤーがない場合は新規に作成してください。このレイヤーのステートマシーンの構造は今回の話とは無関係なので、好きなように構築して構いません。
ただし、Fistの表情用のステートを必ず作ってください。
Animation ParameterのGestureRight/GestureLeftはFistを1で表すので、これらの値が1になったときに遷移するようにすればFistのアニメーションが作れます(GestureRight/GestureLeftがAnimation Controllerにない場合は新規に作成してください。値はIntです)。
以下の画像では右手のFistのステートの作り方を説明しています。

f:id:yakumo890:20211120223943p:plain
Fistに遷移する設定

続いて、Animation ControllerのAnimation Parameterに値を追加します。
追加する値はFloatにしてください。名前は必ずGestureRightWeightGestureLeftWeightにしてください。
これらの違いは、右手のコントローラーか左手のコントローラーかです。右手のコントローラーの握り具合に応じて表情を変える場合はGestureRightWeightという名前に、左手のコントローラーの握り具合に応じて表情を変える場合はGestureLeftWeightという名前にしてください。どちらの手にもアニメーションを付けたい場合はこの両方を追加してください。
これらのパラメーターの値は0のままで構いません。

このFistのステートを設定していきます。 まずは、Motionに上記で作ったアニメーションを設定してください。 次に、Motion Timeの横にあるチェックボックスにチェックをつけます。チェックをつけるとプルダウンメニューが表示されるので、そこにGestureRightWeightかGestureLeftWeightを設定します。繰り返しますが、右手用の表情ならGestureRightWeightで、左手用の表情ならGestureLeftWeightを設定します。
以下の画像ではGestureRightWeightをセットしています。

f:id:yakumo890:20211120224745p:plain
Fistのステートの設定

これで設定は完了です。

4. 確かめる

アバターをアップロードすればVRChatで確かめられますが、Unity上でもある程度の確認はできます。
Hierarchyでアバターを選び、InspectorからAniamtorというコンポーネントのControllerに上記のFXレイヤー用のAnimation Controllerを設定してください。

f:id:yakumo890:20211120225519p:plain
テストのためのAnimatorの設定
この状態でPlayすると、アバターにFX用のAnimation Controllerが適用された状態でSceneが再生されます。
再生した状態でGestureRightもしくはGestureLeftの値を1にし、アバターの表情をFistの表情に変化させます。
この状態で、GestureRightWeightもしくはGestureLeftWeightの値を0から1までの好きな数字に変えます。これにより、アバターの表情が変化したら設定が正常に完了していることになります。
ただし、Animation Parameterの名前が正しくない(スペルが間違っていたりする)場合は、Unity上では動いてもVRChat上では正常に動かなくなるのでスペルが正しいか必ず確認してください。

おわりに

本記事では、コントローラーの握り具合で表情を変化させる方法を説明しました。
筆者が持っているHMDがOculus Quest2ということもあり、Quest2のコントローラーを前提にした説明をしましたが、GestureRightWeightとGestureLeftWeightは他のHMDのコントローラーでも変化させられると考えています。
他のコントローラーでこれらの値を取得する方法(握り方)を知っている方、教えていただけるとありがたいです。