非ランタイムでPlayable Graphを扱う方法をまとめました。
やりたいことと問題点
いま、UnityEditor上で非ランタイムのときにPlayable Graphを使いたいとします。
そこでExecuteAlwaysアトリビュートを付けて、OnEnableでPlayable Graphを生成するようにしました。
(再生処理などは説明のためにいったん省いています)
using UnityEngine; using UnityEngine.Animations; using UnityEngine.Playables; [ExecuteAlways] [RequireComponent(typeof(Animator))] public class Example : MonoBehaviour { private PlayableGraph _playableGraph; private void OnEnable() { if (!_playableGraph.IsValid()) { _playableGraph = PlayableGraph.Create("Animation Playable"); AnimationPlayableOutput.Create(_playableGraph, "Animation", GetComponent<Animator>()); } } private void OnDisable() { if (_playableGraph.IsValid()) { _playableGraph.Destroy(); } } }
これをGameObjectにアタッチすると、非ランタイムでもPlayable Graphが生成されます。
(PlayableGraph Visualizerで確認しています)
これで再生中も非再生中もPlayable Graphを使えるので、一見これでうまくいくように見えるのですが、
DirtyなSceneを保存するとそのタイミングでなぜかPlayable Graphが消えてしまいます。
また、コンパイル時にも消えたりとよくわからない挙動をします。
解決方法
これに対応するためには、PlayableGraphを使う各処理の前でPlayable Graphが生成されているかをチェックします。
using UnityEngine; using UnityEngine.Animations; using UnityEngine.Playables; [ExecuteAlways] [RequireComponent(typeof(Animator))] public class AnimationPlayer : MonoBehaviour { private PlayableGraph _playableGraph; public void Play() { CreateGraphIfNeeded(); _playableGraph.Play(); } public void Stop() { CreateGraphIfNeeded(); _playableGraph.Evaluate(); } private void CreateGraphIfNeeded() { if (!_playableGraph.IsValid()) { _playableGraph = PlayableGraph.Create("Animation Playable"); AnimationPlayableOutput.Create(_playableGraph, "Animation", GetComponent<Animator>()); } } private void OnDestroy() { if (_playableGraph.IsValid()) { _playableGraph.Destroy(); } } }
これで必要な時にPlayableが作られている状態は担保できました。