gologiusの巣

プログラミングなどの技術メモです。誰かの役に立てるとうれしいです。

【Unity】 Playable APIで上半身と下半身を別々のモーションをさせる【改良版】

※2018/03/03追記:バージョンアップでモーションが動かなくなる不具合を修正(最後に説明)

やりたいこと

前回

前回の問題は

  • RigがHumanoidの場合、挙動がおかしい
  • AnimationLayerMixerPlayable の理解が微妙
  • (記事には書いてないけど) そもそもAvaterMaskは一つでいいのでは?
    • AnimatorControllerを使う場合、AvaterMaskは上半身分のみでよい
    • 実装をもうちょいきれいにできるのでは?

でした。解決していきましょう。

実装結果

実際に実装したものがこちら(左:Humanoid、 右がGeneric)

サンプルプロジェクトはこちら

GitHub - gologius/PlayabkeMask: Playable APIでマスクをするテスト

使用方法

1「上半身分」のAvaterMaskを作成する ※前回は下半身分も作成しましたが、いらないことが判明しました。 f:id:gologius:20171120233424p:plain

f:id:gologius:20171120233300p:plain

2 Animatorがアタッチされている場所にMotionPlayerをアタッチ f:id:gologius:20180104005628p:plain

3 先ほど作成したAvaterMaskをMotionPlayerにD&Dでセットする

4 MotionPlayer.play(AnimationClip clip, int layer, bool loop)を何らかの方法で呼ぶ

  • サンプル プロジェクトでは、MotionTest内から呼び出してます
  • AnimationClipもここで指定

解説

f:id:gologius:20180104012133p:plain

  • ※この理解であっているかは不明

  • AnimationMixerPlayableはモーション切り替え時に、変更前モーションと変更後モーションをいい感じでブレンドするためのミキサー。

  • SetLayerMaskFromAvatarMask(1, upperMask)で、LayerIndexとAvaterMask(上書きする部位)を指定している
    • ※ここでいうLayerIndexはAnimationLayerMixerPlayableInputIndexと(おそらく)同じ
    • InputIndexは、ConnectInput()で指定するもの
  • なので、SetLayerMaskFromAvatarMask()したレイヤ番号と同じInputIndexに、上半身用のモーションを流しこめば、 【A】ベースとなるモーション、の該当部分(サンプルの場合上半身)が、【B】のモーションに上書きされる

疑問

AnimationLayerMixerPlayableのWeight全く弄っていないのですが、いいんでしょうかね。。。

※【2018/03/03追記】...という疑問が2018/01時点ではあったんですが、アップデートで見事に修正されました。 恐らく、関数定義がUnity2017.1時点では

AnimationLayerPlayable(int inputIndex, ...... float weight = 1f)

となってたんでしょうが、Unity2017.3では

AnimationLayerPlayable(int inputIndex, ...... float weight = 0f)

になっており、明示的にweightを指定してあげないと、全くモーションが反映されない模様です。 サンプルも修正しました