【Unity】指のポーズをブレンドしてハンドジェスチャーを作ろう
- 概要
- 動作環境
- 使用アセット
- ポーズの用意
- ポーズの簡単な作り方
- UnityでFBXをImport
- Avatar Mask の作成
- AnimatorControllerを作成
- 動作確認
- Additive Reference Pose について
- サンプルプロジェクト
- 雑感
概要
今回は手の指を曲げるアニメーションを組み合わせてハンドジェスチャーの作ってみたいと思います。
UnityにはBlendTreeというアニメーションをブレンドする機能があります。
今回はそのBlendTreeと指のアニメーションを組み合わせることでハンドジェスチャーを実現したいと思います。
動作環境
- Unity 2020.1.1f1
- Blender 2.83
動作確認可能なプロジェクトを記事の最後に記載します。
使用アセット
ポーズの用意
Blenderでモデルを読み込んで、以下のポーズ(BlenderではActions)を作成。
1ポーズに左右の手両方のキーフレーム登録をオススメします。。
後述するAvatar Maskで左右の手のアニメーションを分離できます。
※ポーズの作り方については後述
ポーズの条件
- 0フレーム目は デフォルトの状態
- 0フレーム目は必ずデフォルト(曲げる前)の状態のキーフレームを登録すること
- 1フレーム目は 対象の指を曲げた状態
- 例えば "IndexFingerClosed" であれば、人差し指のみ曲げた状態
用意するポーズ
- HandOpened (いわゆるパーのポーズ、デフォルトのポーズ)
- ThumbClosed (親指のみ閉じたポーズ)
- IndexFingerClosed (人差し指のみ閉じたポーズ)
- MiddleFingerClosed (中指のみ閉じたポーズ)
- RingFingerClosed (薬指のみ閉じたポーズ)
- PinkyFingerClosed (子指のみ閉じたポーズ)
HandOpened
手がパーのポーズ、いわゆるデフォルトポーズ
ThumbClosed, FingerClosed
5本の指それぞれを個別に閉じている状態のポーズを用意。
※親指、中指、薬指、小指は省略
ポーズの簡単な作り方
※Blenderをある程度触ったことがある人向けです。
以下の流れで、それぞれの指のポーズを作成できます。
- 初めにグーのポーズを作る
- グーのポーズから対象の指以外をデフォルトに戻す
グーから作ることによって、すべての指のポーズをブレンドした時にきれいなグーになると思います。
パーからグーを作る方法
Blender グーから一部の指をデフォルトに戻す
アニメーションをExport
以下の手順でBlenderからFbxを算出
- Export対象のモデルを選択
- File -> Export -> FBX(.fbx)
- "Selected Objects"を有効にし、"Object Types"を"Armature"のみする
- 今回はスケルトンポーズ(アニメーション)のみを出力したいため、メッシュは除外
- Export FBX
UnityでFBXをImport
HumanoidとしてImportして、AnimationをHumanoid向けに変換しましょう。
- "Animation Type" を "Humanoid"に変更
- "Apply"
非ループ化
Loop Timeなどは無効のままにしてください。
ブレンド中におかしくなってしまいます。
Animation Clipから不要なキーフレームを削除
必須ではありませんが、HumanoidでImportするとすべてのMuscleのキーフレームが登録されてしまいます。
Animation Clipのサイズが削減できるので不要なキーフレームは削除しておきましょう。
- HandOpened は指以外のキーフレームを削除
- 各FingerClosedは対象の指以外のキーフレームを削除
Avatar Mask の作成
UnityではAvatar Maskを使ってアニメーションの適用範囲をマスクで制限することができます。
- "Project"上で右クリック -> "Create" -> "Avatar Mask"
- アニメーションはループさせない(Loop Time チェックボックスを オフ)
- プレイ中に大変なことになります
- 左右の手それぞれの Avatar Mask を作成
AnimatorControllerを作成
前置きが長かったですがいよいよ本題です。
これまで用意したAnimation(ポーズ)をブレンドするAnimationControllerを用意して、ハンドジェスチャーを作っていきます。
ブレンドの方針
- AnimatorControllerのレイヤーを使用
- "Blending" を "Additive" にし、ベースポーズからの加算によってポーズの組み合わせを実現
簡単に言えば"パー" から"指を曲げるポーズ"を加算することで、ジェスチャーを実現する方針になります。
ベースポーズ用レイヤーを作成
- レイヤーを追加
- Weightを1, Maskに左手用Avatar Mask, BlendingをOverrideに設定
- DefaultStateのアニメーションに "HandOpened" を指定
これでBase Layerの左手のアニメーションが常にパーに上書きされる形になります。
加算用レイヤーを作成
レイヤーの作成
- レイヤーを追加
- Weightを1, Maskに左手用Avatar Mask, BlendingをAdditiveに設定
- DefaultStateにBlendTreeを指定
BlendTreeの設定
- Parametersに
CloseThumb_L
,CloseIndex_L
... の様に左手の指ごとのパラメータをfloatで用意- 右手の指の場合は
CloseThumb_R
,CloseIndex_R
...
- 右手の指の場合は
- "BlendType" に "Direct" を指定
- Motionを5つ追加し、各指のアニメーションとパラメータを指定
動作確認
それでは作ったAnimatorControllerをユニティちゃんのAnimatorに入れて動作確認してみましょう!
うまくいきました!
Additive Reference Pose について
Blenderでアニメーションを作る際、「0フレーム目は デフォルトの状態」という条件を加えました。 実はこれ、"Additive Reference Pose"というものが関係しています。
Additive Reference Pose とは
平たく言えば「Additive(レイヤー)で使用する際にベースとなるポーズ」のことです。
残念ながら"Additive Reference Pose"の明確なドキュメントは見つかりませんでした。。。(知っている方いらっしゃいましたら教えてください!!!)
デフォルトのAdditive Reference Pose
AnimationUtility.SetAdditiveReferencePoseのページにこんな説明があります。
By default any animation clip used in an additive layer use the pose at time 0 to define the reference pose
つまり、"Additive Reference Pose"はデフォルトではそのAnimation Clipの0フレーム目のポーズになるということです。
これが 「0フレーム目は デフォルトの状態」という条件にした最大の理由になります。
余談:Additive Reference Pose を明示的に指定する方法
一応、Additive Reference Pose は明示的に指定する方法があります。
ただ、どれも扱いやすいとは言えないと個人的には思います。。。
ブレンド前提のAnimation Clip は素直にベースのポーズを0フレーム目に指定したほうが良いと思います。
FBXのImport時に指定
以下の方法を使用すると、同一Animation Clip内で0フレーム目以外を"Additive Reference Pose"として指定できます。
- FBXをInspectorで確認し、"Animation"タブを開く
- 下部に"Additive Reference Pose" のチェックボックスをオンにする
- Pose Frameを指定
Debug Inspectorで指定
実はDebug Inspectorにすると、Animation ClipのInspectorに"Additive Reference Pose"を指定する欄が表示されます。
- InspectorをDebug化
- "Additive Reference Pose Clip" と "Additive Reference Pose Time" を指定
- "Has Additive Reference Pose"のチェックボックスをオン
- オンにしていないと"Additive Reference Pose"が有効になりません
AnimationUtility.SetAdditiveReferencePoseを使って指定
※個人的には非推奨
AnimationUtility.SetAdditiveReferencePose を使うことで指定できます。
別のAnimation Clipも指定可能です。
AnimationUtility.SetAdditiveReferencePose(targetClip, referenceClip, poseTime);
メソッド呼び出しの結果を確認したい場合は、前述したDebug Inspectorで確認して下さい。
また、以下のようなツールも作ってみました(プロジェクトにいれています)。
複数のAnimationClipでまとめて"Additive Reference Pose"を指定できます。
ツールの注意点
Set/Reset を繰り返すと以下のようなエラーを吐くことがあります。
こうなるとUnityを再起動しないとうまく動作しません。。。
原因不明なので何か知っている人は良かったら教えてください。
サンプルプロジェクト
雑感
今回はBlender, Animator, Animation Clip, Additive Reference Poseと詰め込みすぎ感がありますねw。
有料アセット使えばUnity内で完結できたと思うんですが、無料でできるようにしたかったのでBlenderも入れてみました。
今回の記事の経緯は手のアニメーション作ってるときに「あれ、これアニメーションの組み合わせでできんじゃね?」と思ったことですね。
Animationの用意やAnimatorの調整など、面倒な部分もありますがモデルに適したAnimation Clipを使えることがメリットでしょうか。
AnimatorControllerOverrideを使えばモデルごとにAnimationClipを設定することも可能です。
"Additive Reference Pose"についてはいいドキュメントが見つからなかったので調べるのがちょっと大変でした。
今のところ手のジェスチャー以外にいい組み合わせは思いつかないですが、 何かよさげな応用例があれば教えてください!
それでは~。