【Unity】自作のPlayableを作成しTimelineで再生できるようにする

Playable API周りについての概要がなんとなくわかってきたので、次にScriptablePlayableを自作してみたいと思い調査をしてみました。 最終目標は独自のTrackをTimelineで再生をすることです。

ScriptPlayable を自作する

ScriptPlayableを作るにはPlayableBehaviourを継承してクラスを作成します。 では適当にPlayableを作ってみます。

public class CustomPlayable : PlayableBehaviour
{
    // PlayableGraph再生時
    public override void OnGraphStart(Playable playable)
    {
        Debug.Log("Graph Start");
    }

    // PlayableGraphストップ時
    public override void OnGraphStop(Playable playable)
    {
        Debug.Log("Graph Stop");
    }
}

これはPlayableGraphで使って見ます。

 _playableGraph = PlayableGraph.Create();
           
var customPlayable = ScriptPlayable<CustomPlayable>.Create(_playableGraph, 0);
        animationPlayableOutput.SetSourcePlayable(customPlayable);
var scriptOutput = ScriptPlayableOutput.Create(_playableGraph, "custom");
scriptOutput.SetSourcePlayable(customPlayable);
            
 _playableGraph.Play();

Unityで再生するとPlayableGraph Visualizerではこのように表示されています。 (デバックログも吐き出されています)

f:id:albatrus:20210708175742p:plain
PlayableGraph Visualizerの中身

ProcessFrame

PlayableBehaviourにProcessFrameというメソッドが定義されています。 PlayableGraph再生時の経過情報を受け取ることができます。

public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{

}

FrameDataにはdeltaTimeなどの情報がありますのでこれを使うことで、何かしらのアニメーションを設定できたりできそうです。

Playableの時間を設定する

現状、Unity再生中にこのPlayableはずっと再生されています。 次に、Playableの再生時間を設定する方法を調べます。

public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
    var time = playable.GetTime();
    var duration = playable.GetDuration();
}

現在の経過時間はPlayableのGetTimeで取得でき、Playableの再生時間はGetDurationで取得ができます。 これを使い、必要な処理を行うことができます。

再生時間はPlayableのSetDurationで指定できます。

playable.SetDuration(1.0f);

ProcessPrameは経過時間を過ぎても呼び出し続けますので、もし止めたい場合には playable.Pause()を呼び出します。

 playable.Pause();

Timelineで使いたい

Playableについて少しわかってきたので、当初の目的であるTimelineで使えるようする方法が調べました。

blog.unity.com

必要なクラス

TImelineで用意するためには次の3つを表示できるクラスです。

  • Track
  • Playable
  • PlayableAsset (Clip)

f:id:albatrus:20210709150426p:plain
PlayableをTimelineで使うために必要な要素

f:id:albatrus:20210709151946p:plain:w300
編集のためのInspector

Playableを定義する

TImelineが再生されたときのClipの挙動をPlayableで作成されています。 今回はUGUIのImageの色を変更するできるように実装をしました。

public class CustomTimelineClipPlayable : PlayableBehaviour
{
    public Color StartColor = Color.white;
    public Color EndColor = Color.white;
    
    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        var image = playerData as Image;
        if (image != null)
        {
            var duration = playable.GetDuration();
            var time = playable.GetTime();
            image.color = Color.Lerp(StartColor, EndColor, (float) (time / duration));
        }
    }
}

Color.Lerpを使って色変化を実装しているのですが、もしかしたらもっと良い方法あるかもしれません。

PlayableAsset

次にTimeline上にClip表示と編集ができるようにPlayableAssetを作成します。 今回はImageの始値終値を設定できるようにしました。

[System.Serializable]
public class CustomTimeLinePlayableAsset : PlayableAsset
{
    public Color startColor = Color.white;
    public Color endColor = Color.white;

    // Factory method that generates a playable based on this asset
    public override Playable CreatePlayable(PlayableGraph graph, GameObject go)
    {
        var playable = ScriptPlayable<CustomTimelineClipPlayable>.Create(graph);
        var behaviour = playable.GetBehaviour();

        // PlayableへInspectorでの設定値を渡しています。
        behaviour.StartColor = startColor;
        behaviour.EndColor = endColor;
        
        return playable;
    }
}

Trackを自作する

Timelineで使うTrackを作成します。

[TrackClipType(typeof(CustomTimeLinePlayableAsset))]
[TrackBindingType(typeof(Image))]
public class CustomTimelineTrack : TrackAsset
{
    
}

TrackBindingTypeで対象のImageを設定できるようにしています。

確認

これで準備完了です。 TimelineでTrackを作成するときに、新しく「CustomTimelineTrack」が選択できるようになっているはずです。

最後に

とりあえず、自作のPlayableをTimeline上で動かせるようになりました。 ただ、簡単なPlayableでしたので、今後はもう少し複雑なPlayableが作れるようにしたいないと思いました。