AnimationLayerMixerPlayableでAnimationClipPlayableにAvatarMaskを適用する方法です。
Unity2018.4.0
やりたいこと
Animator ControllerのLayer機能を使うと、上半身と下半身で別のモーションを適用できます。
見た目はこんな感じになります。
この記事ではこの機能を、Playable Graphを使って実現してみます。
ソースコード
いきなりですがソースコードです。
using UnityEngine; using UnityEngine.Animations; using UnityEngine.Playables; public class PlayableExample : MonoBehaviour { [SerializeField] private AnimationClip _clip1; [SerializeField] private AnimationClip _clip2; [SerializeField] private AvatarMask _mask; private AnimationLayerMixerPlayable _mixer; void Awake() { var graph = PlayableGraph.Create("Example Graph"); AnimationPlayableOutput.Create(graph, "Animation", GetComponent<Animator>()); _mixer = AnimationLayerMixerPlayable.Create(graph, 2); graph.GetOutput(0).SetSourcePlayable(_mixer); // Playableを2つ生成してmixerに繋ぐ var playable1 = AnimationClipPlayable.Create(graph, _clip1); _mixer.ConnectInput(0, playable1, 0); var playable2 = AnimationClipPlayable.Create(graph, _clip2); _mixer.ConnectInput(1, playable2, 0); // 上のレイヤーにマスクを掛ける _mixer.SetLayerMaskFromAvatarMask(1, _mask); // InputWeightは両方とも1にしておく _mixer.SetInputWeight(0, 1); _mixer.SetInputWeight(1, 1); graph.Play(); } }
AnimationLayerMixerPlayableというLayerを実現するMixerが用意されているのでこれを使います。
これにAnimationClipPlayableを二つ繋いで、InputWeightは両方とも1にしておきます。
そして二つ目のレイヤーにはSetLayerMaskFromAvatarMask()
でAvatarMaskを適用します。
これで、Animator ControllerでLayerを二つ作って上のレイヤーにMaskを適用したのと同じ状態が作れました。
結果
上記にAnimationClipやAvatarMaskを設定して再生するとマスクされたモーションが再生されます。
Playable Graphはこんな感じです。
BlendingをAdditiveに
Animator ControllerのLayerにはBlendingという機能があります。
これをAdditiveにすると下のレイヤーとモーションがブレンドされます。
これをPlayableGraphで実装するにはAnimationLayerMixerPlayable.SetLaerAdditive()
を使います。
_mixer.SetLayerAdditive(1, true);
Maskを動的に差し替える
Maskを動的に差し替えることもできるようです。
using UnityEngine; using UnityEngine.Animations; using UnityEngine.Playables; public class PlayableExample : MonoBehaviour { [SerializeField] private AnimationClip _clip1; [SerializeField] private AnimationClip _clip2; [SerializeField] private AvatarMask _mask; [SerializeField] private AvatarMask _mask2; private AnimationLayerMixerPlayable _mixer; void Awake() { var graph = PlayableGraph.Create("Example Graph"); AnimationPlayableOutput.Create(graph, "Animation", GetComponent<Animator>()); _mixer = AnimationLayerMixerPlayable.Create(graph, 2); graph.GetOutput(0).SetSourcePlayable(_mixer); // Playableを2つ生成してmixerに繋ぐ var playable1 = AnimationClipPlayable.Create(graph, _clip1); _mixer.ConnectInput(0, playable1, 0); var playable2 = AnimationClipPlayable.Create(graph, _clip2); _mixer.ConnectInput(1, playable2, 0); // 上のレイヤーにマスクを掛ける _mixer.SetLayerMaskFromAvatarMask(1, _mask); // InputWeightは両方とも1にしておく _mixer.SetInputWeight(0, 1); _mixer.SetInputWeight(1, 1); graph.Play(); } private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { _mixer.SetLayerMaskFromAvatarMask(1, _mask2); } } }
上半身マスクと下半身マスクを切り替えるとこんな感じです。
動的にマスクを削除することはできない?
動的にマスクを削除することはできないようです。
SetLayerMaskFromAvatarMask()
にnullを入れたらできるだろうと思ってやってみたらエラーを吐きました。
動的にマスクを外したければ専用のAvatarMaskを用意してそれに差し替えるなどの対応が必要そうです。