どうも、Reveです。なんやかんやで2週間も経ってしまいましたが、今回も「AIで対話できるキャラづくり」です。
Unityでのアニメーション処理について
キャラクターの動きや表情も大雑把に言えば素材の一つです。
Unityではモーション自体をAnimation Clipという形式のファイルで保管しており、それをAnimation Controllerというファイルで条件に応じてどのモーションを動かすか制御します。そして、動かす3DCGモデルにAnimatorというスクリプトをつけてコントローラー(Animation Controller)を割り当てることで、3DCGモデルが動くようになります。この一連のシステムをAnimation State Machine(ステートマシン)と呼んでいます。つまりAnimator → Animation Controller → Animation Clipという親子(?)関係でモーションを制御しています。
アニメーションステートについての解説はこちらも参照。
モーション作成(というか導入)
まず、前提として3DCGモデルはリグと呼ばれる骨格が仕込まれたものを使います。
そのうえで、リグを動かすモーションを作成、またはどこかからダウンロードして導入します。主に考えられる手段は以下の通りです。
- 3DCGアニメーションソフトを使って作成
- モーションキャプチャを使って作成
- Unityアセットストアや外部サイトから取得
自力での作成はそれなりの機材や手間がかかるので、手っ取り早く作りたい場合はどこかから素材を見つける方が良いと思います(最近では、AIを使って画像や動画の姿勢推定からモーションを作る方法もあるようですが…)。今回は、Unityアセットストアなどから対話型AIキャラに合いそうなモーションを選んでみました。
Anime Girl Idle Animations
お試し版もあります。
『VRMお人形遊び』用アニメーションデータ詰め合わせ
(無料)【VMMモーション詰め合わせ】- VMagicMirror用カスタムモーション
ステートマシン作成
ステートマシンを作るには、まず上記の通りAnimation Controllerを新規作成します。これはプロジェクトタブの新規作成ボタンか右クリックメニューですぐに出来ます。
作成した直後は緑色(Entry)、赤色(Exit)、水色(Any State)、そして橙色(初期状態でIdle)の4つのブロック(ステート)があると思いますが、まずここでは緑色と橙色のものに注目します。
実行された直後は Entry → Idle と状態が遷移して、Idleブロックに割り当てられたアニメーションを実行するので、IdleのMotionを好きなモーション(Animation Clip)を入れればすぐに3Dモデルが動き出します。
ただ、これでは単一のモーションを繰り返すだけなので、別のモーションも入れる場合はもう少し工夫が必要です。
別のモーションを入れるには、ステートを追加したうえでステート間を矢印(Transision)でつなぎます。当然、作成したステートにも対応するAnimation Clipを割り当てます。
そして、パラメータ作成および遷移条件の設定を行います。
前者は Animatorタブの左側にある Parameter を選択して+ボタンを押すと作れます。パラメータは4つの型(Float, Int, Bool, Trigger)から一つを選び、任意の名前を付けます。
後者は先ほどつなげたステート間の矢印がどんな条件で実行されるかを定めるもので、先ほど設定したパラメータで条件を設定します(値が10以上、真理値がtrue等)。なお、条件を指定しない場合、Exit Timeが有効であればモーションの終了時に接続先のものへ移行します。
モーション制御
ただ、このステートマシンを作成しただけではモーションの切り替えはできません。
そこで、先述のパラメータの値をC#スクリプトで変えていくことでモーション遷移を実装します。Animator(Animation Controllerのクラス名)インスタンスにあるメソッドのSet…(Float/Int/Bool/Trigger)メソッドで値を入れることでモーションが切り替えられます。
ですが、パラメータ名の引数が文字列で、型ごとに別のメソッドを分ける必要があるため、このままではパラメータを増やすごとにスクリプトを弄る必要があって面倒です。なので、当方ではAnimationParameterという独自クラスとSetParameterというメソッドを使い、パラメータを増やしてもAnimationParameterの配列をインスペクタ上で編集することで対応できるようにしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
[System.Serializable] public class AnimationParameter { public string name; public AnimatorControllerParameterType type; public string value; } // assign the following parameters [SerializeField] Animator animator; [SerializeField] protected AnimationParameter[] parameters; /// <summary> /// Choose animation parameter /// </summary> /// <param name="num">index of the parameter list</param> /// <param name="reset">whether to reset</param> public void SetParameter(int num, bool reset = false) { var param = parameters[num]; // set value in parameter as matching to its type switch (param.type) { case AnimatorControllerParameterType.Float: if (float.TryParse(param.value, out float fvalue)) { animator.SetFloat(param.name, reset ? 0f : fvalue); } break; case AnimatorControllerParameterType.Int: if (int.TryParse(param.value, out int ivalue)) { animator.SetInteger(param.name, reset ? 0 : ivalue); } break; case AnimatorControllerParameterType.Bool: if (bool.TryParse(param.value, out bool bvalue)) { animator.SetBool(param.name, reset ? false : bvalue); } break; case AnimatorControllerParameterType.Trigger: if (!reset) { animator.SetTrigger(param.name); } else { animator.ResetTrigger(param.name); } break; } } // call the method SetParameter somewhere SetParameter(num); |
リップシンク
リップシンクは表情に関するアニメーションの一種といえます。3Dモデルで表情を作るにはフェイスリグやテクスチャの切替といった手法がありますが、Unityで一般的なのはブレンドシェイプです。これは対象の3Dモデルについて複数パターンの形状を記憶しておき、滑らかにブレンドすることでいろいろな表情などを作れるようにする仕組みです。
リップシンクも自力で実装するのは非常に難しいので、今回はuLipSyncを使います。
3Dモデルのルート(大元)にULipSyncBlendShape、顔のモデルにULipSync(+ AudioSource)を入れて、あいうえお5音に対応するブレンドシェイプを指定すれば、音声に対応して口が変形するようになります。詳細は上のリンク先をご参照ください。
なお、(VRMモデルで)口も動かしつつ目など他の表情も動かしたいときは、VRMInstanceの Runtime >> Update Type を Update に変更する必要がありました。
次回は?
いよいよ終盤。ChatGPTを仕込んでしゃべらせます!