【Unity】【エディタ拡張】非ランタイムでPlayable Graphを扱う方法

非ランタイムで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が生成されます。

f:id:halya_11:20190607133126p:plain
(PlayableGraph Visualizerで確認しています)

これで再生中も非再生中もPlayable Graphを使えるので、一見これでうまくいくように見えるのですが、
DirtyなSceneを保存するとそのタイミングでなぜかPlayable Graphが消えてしまいます。

f:id:halya_11:20190607133238p:plain

また、コンパイル時にも消えたりとよくわからない挙動をします。

解決方法

これに対応するためには、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が作られている状態は担保できました。

関連

light11.hatenadiary.com