UnityのPlayables APIで独自のPlayableを作るときには再利用可能な設計にしておくと便利です。
この記事ではこのような再利用時に便利なカスタムPlayableの作り方を紹介します。
Playables API?
Playables APIの基礎については以下の記事にまとめていますので、必要に応じて参照してください。
再利用のためにはPlayable Behaviourを使う
まず、単純にAnimationClipを生成するだけのPlayableを作ってみます。
普通に作るならAnimationPlayableを直接Playable GraphにつなぐだけでOKです。
しかし今回は再利用可能なPlayableを作るため、Playable Behaviorを使います。
using UnityEngine; using UnityEngine.Animations; using UnityEngine.Playables; public class AnimationClipPlayableBehaviour : PlayableBehaviour { private AnimationClipPlayable _clipPlayable; private Playable _parentPlayable; public PlayableGraph Graph { get { return _parentPlayable.GetGraph(); } } public static ScriptPlayable<AnimationClipPlayableBehaviour> CreatePlayable(PlayableGraph graph) { var scriptPlayable = ScriptPlayable<AnimationClipPlayableBehaviour>.Create(graph, 1); // PlayableBehaviourを初期化 var behaviour = scriptPlayable.GetBehaviour(); behaviour._parentPlayable = scriptPlayable; return scriptPlayable; } public void SetClip(AnimationClip clip) { // AnimationClipPlayableを生成 _clipPlayable = AnimationClipPlayable.Create(Graph, clip); // ParentからすべてのInputをはがす for (int i = 0; i < _parentPlayable.GetInputCount(); i++) { _parentPlayable.DisconnectInput(i); } // くっつける _parentPlayable.SetInputCount(1); _parentPlayable.SetInputWeight(0, 1.0f); Graph.Connect(_clipPlayable, 0, _parentPlayable, 0); } public override void PrepareFrame(Playable scriptPlayable, FrameData info) { if (!_clipPlayable.IsValid()) { return; } _clipPlayable.SetTime(_clipPlayable.GetTime() + info.deltaTime); } }
AnimationClipPlayableの前にPlayableBehaviourを挟む形になります。
Playable Graphにつなぐ
それではこれをPlayable Graphにつないでみます。
using UnityEngine; using UnityEngine.Animations; using UnityEngine.Playables; public class PlayableExample : MonoBehaviour { [SerializeField] private AnimationClip _clip; void Awake() { var graph = PlayableGraph.Create("Example Graph"); AnimationPlayableOutput.Create(graph, "Animation", GetComponent<Animator>()); var playable = AnimationClipPlayableBehaviour.CreatePlayable(graph); playable.GetBehaviour().SetClip(_clip); graph.GetOutput(0).SetSourcePlayable(playable); graph.Play(); } }
AnimationClipをセットして再生するとアニメーションが再生されます。
またこの時のPlayable Graphは次のようになります。
再利用する
それでは次に前々節で作ったPlayableを再利用して二つインスタンス化し、それらをブレンドしてみます。
PlayableBehaviourでラップしているため、以下のようにPlayableBehaviour.Create()
を呼ぶだけで簡単に再利用することができます。
using UnityEngine; using UnityEngine.Animations; using UnityEngine.Playables; public class PlayableExample : MonoBehaviour { [SerializeField] private AnimationClip _clip1; [SerializeField] private AnimationClip _clip2; [SerializeField, Range(0.0f, 1.0f)] private float _blendRate; private AnimationMixerPlayable _mixer; void Awake() { var graph = PlayableGraph.Create("Example Graph"); AnimationPlayableOutput.Create(graph, "Animation", GetComponent<Animator>()); // AnimationMixerPlayableを生成してOutputに繋ぐ _mixer = AnimationMixerPlayable.Create(graph, 2); graph.GetOutput(0).SetSourcePlayable(_mixer); // 1個目のPlayableを生成してmixerに繋ぐ var playable1 = AnimationClipPlayableBehaviour.CreatePlayable(graph); playable1.GetBehaviour().SetClip(_clip1); _mixer.ConnectInput(0, playable1, 0); // 2個目のPlayableを生成してmixerに繋ぐ var playable2 = AnimationClipPlayableBehaviour.CreatePlayable(graph); playable2.GetBehaviour().SetClip(_clip2); _mixer.ConnectInput(1, playable2, 0); graph.Play(); } private void Update() { // ブレンド率に応じてウェイトを設定 _mixer.SetInputWeight(0, 1.0f - _blendRate); _mixer.SetInputWeight(1, _blendRate); } }
クリップを設定して再生してBlend Rateを変えると、アニメーションがブレンドされることが確認できます。
Playable Graphは以下のようになっています。
まとめ
このようにPlayable Behaviourを使うとPlayableを再利用可能な設計にできます。
今回のような簡単な例ではあまり効果はありませんが、複雑なPlayable Graphを組み立てるときにはこのような実装が必要になってくるかと思います。