Version: 2017.2
ScriptPlayable と PlayableBehaviour
アニメーション用語

Playable の例

PlayableGraph Visualizer

PlayableGraph Visualizer は、GitHub で手に入れることができます。このドキュメントでは、PlayableGraph Visualizer (下図) を使用して Playables API で作成したツリーとノードを説明しています。

PlayableGraph Visualizer を使用する手順は以下の通りです。

  1. 使っている Unity のバージョンに適切な PlayableGraph Visualizer を GitHub レポジトリ からダウンロードします。

  2. Window > PlayableGraph Visualizer と選択して、PlayableGraph Visualizer を開きます。

  3. GraphVisualizerClient.Show(PlayableGraph graph, string name) で該当するグラフを登録します。

GraphVisualizer ウィンドウ
GraphVisualizer ウィンドウ

グラフの playable は色のついたノードで示されています。線の色の濃さはブレンドのウェイトを表しています。このツールの詳細は GitHub を参照してください。

ゲームオブジェクトの 1 つのアニメーションクリップを再生

この例は、1 つの playable ノードとリンクする playable 出力を持つ、簡単な PlayableGraph を示しています。playable ノードは 1 つのアニメーションクリップ (クリップ) を再生します。AnimationClipPlayable でアニメーションクリップをラップし、Playables API と互換性を持つようにする必要があります。


using UnityEngine;

using UnityEngine.Playables;

using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]

public class PlayAnimationSample : MonoBehaviour

{

    public AnimationClip clip;

    PlayableGraph playableGraph;

    void Start()

    {

        playableGraph = PlayableGraph.Create();

        playableGraph.SetTimeUpdateMode(DirectorUpdateMode.GameTime);

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

        // playable でクリップをラップします

        var clipPlayable = AnimationClipPlayable.Create(playableGraph, clip);

        // Playable を output に接続します

        playableOutput.SetSourcePlayable(clipPlayable);

        // グラフを再生します

        playableGraph.Play();

    }

    void OnDisable()

    {

        // グラフで作成されたすべての Playables と PlayableOutputs を破棄します

        playableGraph.Destroy();

    }

}

PlayAnimationSample によって生成された PlayableGraph
PlayAnimationSample によって生成された PlayableGraph

以下の例のように、AnimationPlayableUtilities を使用すると、アニメーションの playable の作成と再生を簡易化できます。 __


using UnityEngine;

using UnityEngine.Playables;

using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]

public class PlayAnimationUtilitiesSample : MonoBehaviour

{

    public AnimationClip clip;

    PlayableGraph playableGraph;

    void Start()

    {

        AnimationPlayableUtilities.PlayClip(GetComponent<Animator>(), clip, out playableGraph);

    }

    void OnDisable()

    {

        // グラフで作成されたすべての Playables と Outputs を破棄します

        playableGraph.Destroy();

    }

}

アニメーションブレンドツリーの作成

この例は、2 つのアニメーションクリップをブレンドするための AnimationMixerPlayable の使い方を示しています。アニメーションクリップをブレンドする前に、それらを playable でラップする必要があります。これを行うには、AnimationClipPlayable (clipPlayable0 と clipPlayable1) はそれぞれの AnimationClip (clip0 と clip1) をラップします。SetInputWeight() メソッドは、動的に各 playable のブレンドウェイトを調整します。

この例にはありませんが、 playable ミキサーと他の playable をブレンドするために AnimationMixerPlayable を利用することもできます。


using UnityEngine;

using UnityEngine.Playables;

using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]

public class MixAnimationSample : MonoBehaviour

{

    public AnimationClip clip0;

    public AnimationClip clip1;

    public float weight;

    PlayableGraph playableGraph;

    AnimationMixerPlayable mixerPlayable;

    void Start()

    {

        // グラフとミキサーを作成し、それらを Animator にバインドします

        playableGraph = PlayableGraph.Create();

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

        mixerPlayable = AnimationMixerPlayable.Create(playableGraph, 2);

        playableOutput.SetSourcePlayable(mixerPlayable);

        // AnimationClipPlayable を作成し、それをミキサーに接続します

        var clipPlayable0 = AnimationClipPlayable.Create(playableGraph, clip0);

        var clipPlayable1 = AnimationClipPlayable.Create(playableGraph, clip1);

        playableGraph.Connect(clipPlayable0, 0, mixerPlayable, 0);

        playableGraph.Connect(clipPlayable1, 0, mixerPlayable, 1);

        

        // Graph を再生します

        playableGraph.Play();

    }

    void Update()

    {

        weight = Mathf.Clamp01(weight);

        mixerPlayable.SetInputWeight(0, 1.0f-weight);

        mixerPlayable.SetInputWeight(1, weight);

    }

    void OnDisable()

    {

        // グラフで作成したすべての Playables と Outputs を破棄します

        playableGraph.Destroy();

    }

}

MixAnimationSample によって生成された PlayableGraph
MixAnimationSample によって生成された PlayableGraph

AnimationClip と AnimatorController のブレンド

この例は、AnimationClipAnimatorController とブレンドするための AnimationMixerPlayable の使い方を示しています。

AnimationClipAnimatorController をブレンドする前に、それらを playable でラップする必要があります。これを行うために、AnimationClipPlayable (clipPlayable) は AnimationClip (clip) をラップし、AnimatorControllerPlayable (ctrlPlayable) は RuntimeAnimatorController (controller) をラップします。SetInputWeight() メソッドは、動的に各 playable のブレンドウェイトを調整します。


using UnityEngine;

using UnityEngine.Playables;

using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]

public class RuntimeControllerSample : MonoBehaviour

{

    public AnimationClip clip;

    public RuntimeAnimatorController controller;

    public float weight;

    PlayableGraph playableGraph;

    AnimationMixerPlayable mixerPlayable;

    void Start()

    {

        // グラフとミキサーを作成し、それらを Animator にバインドします

        playableGraph = PlayableGraph.Create();

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

        mixerPlayable = AnimationMixerPlayable.Create(playableGraph, 2);

        playableOutput.SetSourcePlayable(mixerPlayable);

        // AnimationClipPlayable を作成し、それをミキサーに接続します

        var clipPlayable = AnimationClipPlayable.Create(playableGraph, clip);

        var ctrlPlayable = AnimatorControllerPlayable.Create(playableGraph, controller);

        playableGraph.Connect(clipPlayable, 0, mixerPlayable, 0);

        playableGraph.Connect(ctrlPlayable, 0, mixerPlayable, 1);

        

        // Graph を再生します

        playableGraph.Play();

    }

    void Update()

    {

        weight = Mathf.Clamp01(weight);

        mixerPlayable.SetInputWeight(0, 1.0f-weight);

        mixerPlayable.SetInputWeight(1, weight);

    }

    void OnDisable()

    {

        // グラフで作成したすべての Playables と Outputs を破棄します

        playableGraph.Destroy();

    }

}

複数の出力を持つ PlayableGraph の作成

この例は、2 つの異なる playable 出力の型 AudioPlayableOutputAnimationPlayableOutput を持つ PlayableGraph を作成する方法を示しています。

さらに、この例は、 AudioPlayableOutput に接続した AudioClipPlayable を使って、 AudioClip を再生する方法を示しています。


using UnityEngine;

using UnityEngine.Animations;

using UnityEngine.Audio;

using UnityEngine.Playables;

[RequireComponent(typeof(Animator))]

[RequireComponent(typeof(AudioSource))]

public class MultiOutputSample : MonoBehaviour

{

    public AnimationClip animationClip;

    public AudioClip audioClip;

    PlayableGraph playableGraph;

    void Start()

    {

        playableGraph = PlayableGraph.Create();

        // output を作成します

        var animationOutput = AnimationPlayableOutput.Create(playableGraph, "Animation", GetComponent<Animator>());

        var audioOutput = AudioPlayableOutput.Create(playableGraph, "Audio", GetComponent<AudioSource>());

        

        // playables を作成します

        var animationClipPlayable = AnimationClipPlayable.Create(playableGraph, animationClip);

        var audioClipPlayable = AudioClipPlayable.Create(playableGraph, audioClip, true);

        // playables を output に接続します

        animationOutput.SetSourcePlayable(animationClipPlayable);

        audioOutput.SetSourcePlayable(audioClipPlayable);

        // Graph を再生します

        playableGraph.Play();

    }

    void OnDisable()

    {

        // グラフで作成されたすべての Playables と Outputs を破棄します

        playableGraph.Destroy();

    }

}

MultiOutputSample によって生成された PlayableGraph
MultiOutputSample によって生成された PlayableGraph

ツリーの再生ステートの制御

この例は、PlayableGraph ツリーでノードの再生ステートを制御する Playable.SetPlayState() メソッドの使い方を示しています。SetPlayState メソッドは、ツリー全体、ブランチの中の 1 つや、1 つのノードの再生ステートを制御します。

ノードの再生ステートを設定すると、そのステートは、子の再生ステートにかかわらず、すべての子に伝播します。例えば、任意の子ノードが明示的に一時停止だとします。親ノードを「再生中」に設定すると、そのすべての子ノードも「再生中」に設定されます。

この例では、PlayableGraph は 2 つのアニメーションクリップをブレンドするミキサーを持っています。AnimationClipPlayable は各アニメーションクリップをラップし、SetPlayState() メソッドは明示的に 2 つめの playable を一時停止させます。すると、2 つめの AnimationClipPlayable も一時停止します。そのため、その内部時間は進まず、同じ値を出力します。その値は、AnimationClipPlayable が一時停止したときの時刻によります。


using UnityEngine;

using UnityEngine.Playables;

using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]

public class PauseSubGraphAnimationSample : MonoBehaviour

{

    public AnimationClip clip0;

    public AnimationClip clip1;

    PlayableGraph playableGraph;

    AnimationMixerPlayable mixerPlayable;

    void Start()

    {

        // グラフとミキサーを作成し、それらを Animator にバインドします

        playableGraph = PlayableGraph.Create();

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

        mixerPlayable = AnimationMixerPlayable.Create(playableGraph, 2);

        playableOutput.SetSourcePlayable(mixerPlayable);

        // AnimationClipPlayable を作成し、それをミキサーに接続します

        var clipPlayable0 = AnimationClipPlayable.Create(playableGraph, clip0);

        var clipPlayable1 = AnimationClipPlayable.Create(playableGraph, clip1);

        playableGraph.Connect(clipPlayable0, 0, mixerPlayable, 0);

        playableGraph.Connect(clipPlayable1, 0, mixerPlayable, 1);

        mixerPlayable.SetInputWeight(0, 1.0f);

        mixerPlayable.SetInputWeight(1, 1.0f);

        clipPlayable1.SetPlayState(PlayState.Paused);

        //  Graph を再生します

        playableGraph.Play();

    }

    void OnDisable()

    {

        // グラフで作成したすべての Playables と Outputs を破棄します

        playableGraph.Destroy();

    }

}

PauseSubGraphAnimationSample によって生成された PlayableGraph。2 番目のクリップが一時停止しています (赤い枠)。
PauseSubGraphAnimationSample によって生成された PlayableGraph。2 番目のクリップが一時停止しています (赤い枠)。

ツリーのタイミングの制御

この例は、PlayableGraph を再生するための Play() メソッドの使い方、playable を一時停止するための SetPlayState() メソッドの使い方、変数を使って手動で playable のローカルタイムを設定する SetTime() メソッドの使い方を示しています。


using UnityEngine;

using UnityEngine.Playables;

using UnityEngine.Animations;

[RequireComponent(typeof(Animator))]

public class PlayWithTimeControlSample : MonoBehaviour

{

    public AnimationClip clip;

    public float time;

    PlayableGraph playableGraph;

    AnimationClipPlayable playableClip;

    void Start()

    {

        playableGraph = PlayableGraph.Create();

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

        // クリップを playable にラップします

        playableClip = AnimationClipPlayable.Create(playableGraph, clip);

        //Playable を output に接続します

        playableOutput.SetSourcePlayable(playableClip);

        // Graph を再生します

        playableGraph.Play();

        // 時間が自動的に進むのを停止します

        playableClip.SetPlayState(PlayState.Paused);

    }

    void Update () 

    {

        // 手動で時間を制御します

        playableClip.SetTime(time);

    }

    

    void OnDisable()

    {

        // グラフで作成されたすべての Playables と Outputs を破棄します

        playableGraph.Destroy();

    }

}

PlayableBehaviour の作成

この例は、PlayableBehaviour public クラスでカスタムの playable を作成する方法を示しています。また、PlayableGraph のノードを制御する PrepareFrame() 仮想メソッドをオーバーライドする方法も紹介しています。カスタムの playable は PlayableBehaviour クラスの他の仮想メソッドをすべて、オーバーライドできます。

この例では、制御されるノードは一連のアニメーションクリップ (clipsToPlay) です。SetInputMethod() は各アニメーションクリップのブレンドウェイトを変更し、確実に 1 度に 1 つのクリップだけが再生するようにします。SetTime() メソッドがローカル時間を調整し、アニメーションクリップが有効になった時点で、再生が開始します。


using UnityEngine;

using UnityEngine.Animations;

using UnityEngine.Playables;

public class PlayQueuePlayable : PlayableBehaviour

{

    private int m_CurrentClipIndex = -1;

    private float m_TimeToNextClip;

    private Playable mixer;

    public void Initialize(AnimationClip[] clipsToPlay, Playable owner, PlayableGraph graph)

    {

        owner.SetInputCount(1);

        mixer = AnimationMixerPlayable.Create(graph, clipsToPlay.Length);

        graph.Connect(mixer, 0, owner, 0);

        owner.SetInputWeight(0, 1);

        for (int clipIndex = 0 ; clipIndex < mixer.GetInputCount() ; ++clipIndex)

        {

            graph.Connect(AnimationClipPlayable.Create(graph, clipsToPlay[clipIndex]), 0, mixer, clipIndex);

            mixer.SetInputWeight(clipIndex, 1.0f);

        }

    }

    override public void PrepareFrame(Playable owner, FrameData info)

    {

        if (mixer.GetInputCount() == 0)

            return;

        // 必要に応じて、次のクリップに進みます

        m_TimeToNextClip -= (float)info.deltaTime;

        if (m_TimeToNextClip <= 0.0f)

        {

            m_CurrentClipIndex++;

            if (m_CurrentClipIndex >= mixer.GetInputCount())

                m_CurrentClipIndex = 0;

            var currentClip = (AnimationClipPlayable)mixer.GetInput(m_CurrentClipIndex);

            // 時間をリセットします。それで、次のクリップが正確な位置で開始します。

            currentClip.SetTime(0);

            m_TimeToNextClip = currentClip.GetAnimationClip().length;

        }

        // 入力のウェイトを調整します

        for (int clipIndex = 0 ; clipIndex < mixer.GetInputCount(); ++clipIndex)

        {

            if (clipIndex == m_CurrentClipIndex)

                mixer.SetInputWeight(clipIndex, 1.0f);

            else

                mixer.SetInputWeight(clipIndex, 0.0f);

        }

    }

}

[RequireComponent(typeof (Animator))]

public class PlayQueueSample : MonoBehaviour

{

    public AnimationClip[] clipsToPlay;

    PlayableGraph playableGraph;

    void Start()

    {

        playableGraph = PlayableGraph.Create();

        var playQueuePlayable = ScriptPlayable<PlayQueuePlayable>.Create(playableGraph);

        var playQueue = playQueuePlayable.GetBehaviour();

        playQueue.Initialize(clipsToPlay, playQueuePlayable, playableGraph);

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

     playableOutput.SetSourcePlayable(playQueuePlayable);

                 playableOutput.SetSourceInputPort(0);

        playableGraph.Play();

    }

    void OnDisable()

    {

        // グラフで作成したすべての Playables と Outputs を破棄します

        playableGraph.Destroy();

    }

}

PlayQueueSample に生成された PlayableGraph
PlayQueueSample に生成された PlayableGraph

  • 2017–07–04 限られた 編集レビュー でパブリッシュされたページ

  • 2017–07–04 Unity 2017.1 で新規NewIn20171

ScriptPlayable と PlayableBehaviour
アニメーション用語