Animator Controllerを上手く使ってハンドサイン、リップシンク、まばたき、表情遷移をする

こんにちは。八ツ橋まろんです。

この記事では、UnityのAnimator Controllerについて解説します。

本記事で解説するのは、pixivFANBOXで公開しているモーションキャプチャ用unitypackage「VR Motion Recorder」で実装されている機能のうち、Viveコントローラによるハンドサイン、リップシンク、まばたき、表情遷移の制御に関する部分のAnimator Controllerの実装の解説になります。
https://www.pixiv.net/fanbox/creator/16717003/post/566230

3DのバーチャルYouTuberを動かすシステムはいくつかありますが、HTC Viveのような家庭用VR機器は機器が比較的安価かつトラッキングの性能がそこそこ良いため、企業系のVtuberによく採用されています。

HTC Viveのコントローラやトラッカーとアバターとの連動は有料アセットのFinal IKを使う例が大半で、多くの場合、身体のトラッキングはFinal IKだけで済んでしまいます。アバターを動かすだけならこれで十分ですが、更に表現の幅を広げたい場合は、以下のような機能の追加が考えられます。

・指のコントロール
・表情のコントロール
・リップシンク
・まばたき

これらは、フェイストラッキング用のカメラやハンドトラッキング用のグローブなどを併用することで実現できますが、システム全体が高価かつ複雑になってしまうため、HTC Viveの両手のコントローラによる制御で代用する方法があります。

この記事では、Viveのコントローラのボタン(タッチパッドやグリップの入力)によって上記の機能を実現する方法を紹介します。前提知識として、UnityのAnimatorの機能をある程度使える必要があります。(VRChatで遊んでいる人なら、表情のカスタムをしたことがあればおそらく大丈夫です。)

環境
-
Unity2017.4.28f1
Windows 10
HTC Vive


Animator Controllerの基本
-
Animator Controller (以下Animator) を使うと、Animationの遷移ができます。
下の画像はAnimatorの例です。

このAnimatorの基本動作を書きます。
・Sceneが再生されると、緑色のEntry状態からスタートして、矢印に従いオレンジ色のFace 0 (default)状態に遷移します。
・水色のAnyStateは「どの状態からでも」という意味です。どのアニメーション状態にいても、条件を満たせばいつでもAnyStateから伸びる矢印に遷移します。
・現在、ParemeterのFaceは2なので、AnyStateからFace=2で遷移するFace 2状態に遷移します。
・よって、現在はFace 2状態のアニメーション「にっこり」が再生されて、アバターがにっこり笑っています。

![Qiita_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478685/f4c7f288-8d6e-5bfa-d23e-9aaacfe4fbd7.png)





Animator Controllerの応用
-
Animatorにはレイヤー機能(Layer)があります。Layerによって、複雑なアニメーションの遷移を簡単にすることができます。
例えば、下の図はLayerのマスク機能(Mask)を使った例で、Hand Sign (L)というLayerでアバターの左手を制御しています。
この例では、Base LayerというLayer(一番上のレイヤー)でAスタンス(手を下した立ち姿で両手はパーにする)のアニメーションが指定されているのですが、Hand Sign (L)より上側にあるLayer(いま言ったBase Layerや、Face Expressionなど)のレイヤーでポーズが指定されていても、左手だけはHand Sign (L)によってアニメーションが上書きされるため、図では左手がチョキをしています。

実はこのチョキのアニメーションは、本来両手をチョキにするアニメーションなのですが、Maskで左手以外の部位をマスクしているため、右手には影響を与えません。

![Qiita_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478685/0e5f1d8a-4dfa-c927-f2b8-1181062b86ce.png)




また、以下の図のように、LayerのWeightを使い、スクリプトでWeightを上げ下げして口を開けたり閉じたりすることで、口パクなどが再現できます。
下の図では、Lyp SyncというLayerで口を開けた状態のアニメーションを指定し、そのWeightを変えることで口を開けたり閉じたりしています。
このとき、Maskによって他の部位に影響がないように、全ての部分をマスクしています。
![Qiita_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478685/f62f509a-7e00-c5f6-9e67-04c974baf051.png)





Custom Override Controllerの基本
-
Animatorの関連にCustom Override Controllerというものがあります。
これは、作成済みのAnimatorの構造をそのまま真似して、中身のアニメーションだけ差し替えるという使い方をするための物です。格闘ゲームなんかで言うと、Aボタンで攻撃、Bボタンでジャンプという遷移構造は全キャラクター共通なのでAnimatorで構造を作り、しかし攻撃モーションやジャンプモーションはキャラ毎に違うため、キャラクターごとにCustom Override Controllerを作成し、Animatorの構造だけ真似して、中身のアニメーションを差し替える、といった使い方です。

Custom Override Controllerで模倣するAnimatorを指定すると、このような画面が出てきます(下図右側)。既存のアニメーションに差し替えたいアニメーションを入れるだけなので、使い方がシンプルでわかりやすいです。
下の図では、左側の赤枠のHand (L)0～6のアニメーションの中身は、右側の赤枠のHand (L)0～6でアニメーションを指定しています。
下図右側でアニメーションがNoneになっている箇所は、元のAnimatorで指定されたアニメーションが適用されます。
![Qiita_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478685/28ced1d2-e5b4-d659-9393-cbc73a4b0f88.png)


ハンドサイン、リップシンク、まばたき、表情遷移の実装
-
完成図を先に示します。こちらがAnimator
![Qiita_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478685/1b80b6a5-e993-cdbc-bbe7-9d9ed7c3fd35.png)


こちらがMask
![Qiita_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478685/f0bd4e47-6d7e-d592-9f25-c2285f43bd84.png)


こちらがViveコントローラの割り当て表
(割り当てるやり方についてはSteamVR Pluginの導入などが必要になるので別記事にします)
左手のコントローラの操作によって下図右のAnimatorのパラメータのHand (L)が0～6に変化します。
右手のコントローラの操作によって下図右のAnimatorのパラメータのHand (R)と、Faceが0～6に変化します。
(これはスクリプトによって制御しているので、その中身についてはこの記事では割愛。こういう風に割り当てたということだけ理解してもらえればよい。)
![Qiita_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478685/d607e2e8-952a-6a6c-cf31-e4c05ac8e2c7.png)



🌟ハンドサインについて
左コントローラでHand (L)が変更され左手のハンドサインが変更されます。
右コントローラでHand (R)が変更され右手のハンドサインが変更されます。

🌟表情について
右コントローラでFaceが変更され、表情を変更します。
つまり右手のハンドサインも一緒に変更されます。

🌟リップシンクについて
右コントローラでLypSyncが変更され、リップシンクの ON / OFFを変更します。
つまり右手のハンドサインも一緒に変更されます。

🌟自動まばたきについて
右コントローラでAutoBlinkが変更され、自動まばたきのON / OFFを変更します。
つまり右手のハンドサインも一緒に変更されます。



そして、このAnimatorを指定したCustom Override Controllerを作ってやります。このCustom Override Controllerの中に表情やハンドサインなどのアニメーションを入れます。
![Qiita_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478685/887639a3-07be-5e44-2d30-1ccef9b205bd.png)



実際の動作
-
🌟左手の動作
左コントローラは左手のハンドサインの変更のみ行うので、動作は簡単ですので割愛します。

🌟右手の動作
右コントローラのハンドサインの部分の動作は簡単ですので割愛します。

🌟表情、まばたき、リップシンクの動作
右コントローラの状態が5のとき(=コントローラのトリガーを引いているとき)、スクリプトによってAnimatorのパラメータがFace = 5になるため、AnyStateからの遷移でFace 5、Auto Blink 5、Lip Sync 5のモーションが適用されます。上のCustom Override Controllerで言うとFace 5(目閉じ) / Blink 5(None) / LipSync 5(LypSync)のアニメーションが適用されます。

このとき、ベースとなる表情はFace 5(目閉じ)です。

別途のスクリプト(別記事にします)によってLipSync LayerのWeightとマイク音量を連動させると口パクします。
Animatorによって表情ごとにリップシンクの口の形を指定するので、「怒った表情では口を大きく開けたリップシンクをしたい」場合にも対応できます。
逆に、口パクを設定したくない表情では、アニメーションを設定しない(=None)にすることでリップシンクをOFFにできます。

同じように、別途のスクリプト(別記事にします)によってAutoBlink LayerのWeightを制御すると自動でまばたきをします。
これも、まばたきを設定したくない表情では、アニメーションを設定しない(=None)にすることでまばたきをOFFにできます。

おわりに
-
バーチャルキャラクターの実在感を出すにはハンドサインやリップシンク、まばたき、表情遷移がとても効果的です。これら全てをカメラやセンサーでトラッキングできなくとも、コントローラで操作し慣れることでトラッキングと同等以上に自然な動きができるようになります。特に表情に関して言えば、現実で笑ってなくても笑い顔を作れるのでトラッキングよりも便利かも（笑）

Unityを駆使して実在感のあるワンランク上の表現力を身につけていきましょ～！



以上、Animatorの遷移やLayer, Weight, Maskを上手く使ってハンドサイン、リップシンク、まばたき、表情遷移をする解説記事でした！