【PlayableAPI】アニメーションPlayableの使い方

PlayableAPIを使ってモーション(アニメーション)の再生してみます。
Unity側で用意されているモーションを再生する仕組みには、SimpleAnimationやTimelineやAnimationControllerを使う方法がありますが、
そういった高機能な仕組みでは実装しづらい、またはできない場合に使えそうです。

環境:Unity2021.3.3f1(win10)

モーションを再生する(基本)

モーションを再生するのにはAnimationClipPlayableAnimationPlayableOutputを使います。

using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]
public class TestAnimationPlayableExample : MonoBehaviour
{
    [SerializeField] private AnimationClip animeClip; //予めアタッチしておくこと

    private void Start()
    {
        PlayableGraph _playableGraph = PlayableGraph.Create("Example Playable");

        // モーションを設定
        AnimationClipPlayable clip1Playable = AnimationClipPlayable.Create(_playableGraph, animeClip);
        AnimationPlayableOutput playableOutput 
                = AnimationPlayableOutput.Create(_playableGraph, "Animation", GetComponent<Animator>());
        playableOutput.SetSourcePlayable(clip1Playable);

        _playableGraph.Play();
    }

    private void OnDisable()
    {
        _playableGraph.Destroy();
    }

このスクリプトをAnimatorをアタッチされたゲームオブジェクトにアタッチすればモーションが再生されます。

AnimationPlayableUtilities で簡単に書くこともできる

単純に1つのモーションを再生するなら、AnimationPlayableUtilitiesを使って簡単に書くこともできるようになってた。お手軽!

using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]
public class TestAnimationPlayableExample : MonoBehaviour
{
    private PlayableGraph _playableGraph;
    [SerializeField] private AnimationClip animeClip;

    private void Start()
    {
        Animator animator = GetComponent<Animator>();
        AnimationClipPlayable clip1Playable = AnimationPlayableUtilities.PlayClip(animator, animeClip, out _playableGraph);
    }

    private void OnDisable()
    {
        _playableGraph.Destroy();
    }
}

モーションをブレンドする

ブレンド?

モーションの切り替わりによく使われる仕組みで、
複数のモーションを同時に再生し、その割合(ウェイトと呼ばれることの方が多い)を決めることができる仕組み。
例えば、歩行モーション→走るモーションに切り替わる際に、すぐに切り替えてしまうと不自然な場合が多い。
そこで走るモーションの割合を少しずつ増やしていって、徐々にモーションを切り替えることで自然に見せることができる。


ブレンドするにはAnimationMixerPlayableを使って複数のモーションを登録します。

以下のソースの例は、インスペクタのRangeで2つのモーションの割合を切り替える例です。
AnimationMixerPlayable#SetInputWeight でウェイト設定できます。

AnimationMixerPlayable#ConnectInputの1つ目の引数にいれている数字は、
AnimationMixerPlayable#SetInputWeight の1つ目の引数の数字と対応していて、対象のモーションに対してウェイトを設定します。

using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]
public class TestAnimationPlayableExample : MonoBehaviour
{
    private PlayableGraph _playableGraph;

    [SerializeField] [Range(0, 1)] private float weight;

    AnimationMixerPlayable mixer;

    [SerializeField] private AnimationClip animeClip;
    [SerializeField] private AnimationClip animeClip2;

    private void Start()
    {
        _playableGraph = PlayableGraph.Create("Example Playable");

        AnimationClipPlayable clip1Playable = AnimationClipPlayable.Create(_playableGraph, animeClip);
        AnimationClipPlayable clip2Playable = AnimationClipPlayable.Create(_playableGraph, animeClip2);

        //ブレンド
        mixer = AnimationMixerPlayable.Create(_playableGraph, 2);
        mixer.ConnectInput(0, clip1Playable, 0);
        mixer.ConnectInput(1, clip2Playable, 0);

        AnimationPlayableOutput playableOutput
                 = AnimationPlayableOutput.Create(_playableGraph, "Animation", GetComponent<Animator>());

        //ブレンドしたmixerを設定する
        playableOutput.SetSourcePlayable(mixer);

        _playableGraph.Play();
    }

    private void Update()
    {
        //2つのモーションのブレンド割合を切り替える
        mixer.SetInputWeight(0, weight);
        mixer.SetInputWeight(1, 1 - weight);
    }

    private void OnDisable()
    {
        _playableGraph.Destroy();
    }
}


▼Weightを1にすると静かめの待機モーションで、0にすると激しめ(笑)のモーションに徐々に切り替わる。

▼PlayableGraph Visualizerでみると複数のAnimationClipをMixerしてるのがわかりやすい

レイヤーごとにモーションを設定する

レイヤー?

ブレンドの他にも複数のモーションを同時に再生する仕組みとしてレイヤーがあります。
上半身と下半身でモーションを分けてる場合だったり…
AnimationControllerを使っている人は一発でわかりますが、これ↓のことです。


というわけで、上半身用と下半身用のモーションを用意してみました。


レイヤーの設定するにはAnimationLayerMixerPlayableを使います。ソースはほとんどブレンドと変わらないのでわかりやすいと思います。

using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]
public class TestAnimationPlayableExample : MonoBehaviour
{
    private PlayableGraph _playableGraph;

    [SerializeField] private AnimationClip topAnimeClip;
    [SerializeField] private AnimationClip bottomAnimeClip;

    private void Start()
    {
        _playableGraph = PlayableGraph.Create("Example Playable");

        //レイヤー
        AnimationClipPlayable topClipPlayable = AnimationClipPlayable.Create(_playableGraph, topAnimeClip);
        AnimationClipPlayable bottomClipPlayable = AnimationClipPlayable.Create(_playableGraph, bottomAnimeClip);
        AnimationLayerMixerPlayable layerMixer = AnimationLayerMixerPlayable.Create(_playableGraph, 2);
        
        layerMixer.ConnectInput(0, topClipPlayable, 0, 1);//最後の引数はウェイト
        layerMixer.ConnectInput(1, bottomClipPlayable, 0, 1);//最後の引数はウェイト
        AnimationPlayableOutput playableOutput 
                = AnimationPlayableOutput.Create(_playableGraph, "Animation", GetComponent<Animator>());
        playableOutput.SetSourcePlayable(layerMixer);

        _playableGraph.Play();
    }

    private void OnDisable()
    {
        _playableGraph.Destroy();
    }
}


▼結果:こんな風に両方のモーションが再生されます

▼PlayableGraph Visualizerでみると複数のAnimationClipをLayerMixerしてるのがわかる

関連記事

www.snoopopo.com