【Unity】Timelineを拡張して自由にプロパティをコントロールする4つの方法総まとめ

Timelineを拡張して、自由にプロパティをコントロールする4つの方法をまとめました。

Unity2018.3.9

はじめに

この記事ではUnityのTimelineで独自のクリップやトラックを作る方法をまとめます。
Timelineの基本的な使い方は次の記事を参照してください。

light11.hatenadiary.com

またカスタムクリップやカスタムトラックを作成する場合にはPlayable APIの基礎知識が前提となりますが、
Playable APIについては次の記事にまとめています。

light11.hatenadiary.com

まずはお手軽にMonoBehaviourのプロパティをコントロール

さて一点目は最もシンプルな方法です。
まずpublicなプロパティを定義し、LateUpdate()でそれを反映するようなMonoBehaviourを作ります。

using UnityEngine;

public class Example : MonoBehaviour
{
    public float Rotation { get; set; }

    // TimelineがUpdateで値を反映するのでLateUpdateで値を適用する
    public void LateUpdate()
    {
        transform.rotation *= Quaternion.AngleAxis(Rotation, Vector3.up);
    }
}

これをAnimation Trackで動かすだけです。

f:id:halya_11:20190325231606p:plain

PostEffectなど、Animationから直接触れられないプロパティをコントロールするのによさそうです。

ITimeControlを実装するだけで既存クラスがTimelineに対応

二つ目はITimeControlを使う方法です。
まずITimeControlを実装したMonoBehaviourを作成します。

using UnityEngine;
using UnityEngine.Timeline;

public class Example : MonoBehaviour, ITimeControl
{
    /// <summary>
    /// クリップに入った時に呼ばれる
    /// </summary>
    public void OnControlTimeStart()
    {
        gameObject.SetActive(true);
    }

    /// <summary>
    /// クリップから出た時に呼ばれる
    /// </summary>
    public void OnControlTimeStop()
    {
        gameObject.SetActive(false);
    }

    /// <summary>
    /// クリップがアクティブな時に毎フレーム呼ばれる
    /// </summary>
    public void SetTime(double time)
    {
        transform.rotation *= Quaternion.AngleAxis(Mathf.Pow((float)time, 2.0f), Vector3.up);
    }
}

このスクリプトを適当なGameObjectにアタッチしておきます。
そしてControlTrackのにこのGameObjectをセットします。

f:id:halya_11:20190325225814p:plain

するとTimelineからITimeControlのメソッドが呼ばれるようになります。

f:id:halya_11:20190325230222g:plain

この方法も実装はシンプルですが、detaTimeやクリップの長さなどが取れないので複雑な処理はできません。

ちゃんとやるならPlayableTrack用のカスタムクリップを作る

次にPlayableTrack用のカスタムクリップを作る方法です。
クリップを作るにはPlayableBehaviourを継承したクラスとPlayableAssetを継承したクラスを作ります。
まずPlayableBehaviourを継承したクラスのソースコードです。

using UnityEngine;
using UnityEngine.Playables;

public class ExamplePlayableBehaviour : PlayableBehaviour // PlayableBehaviourを継承する
{
    public Renderer Renderer { get; set; }
    public Color StartColor { get; set; }
    public Color EndColor { get; set; }

    private Material _material;
    
    // フレーム毎の処理
    // 非ランタイムでも呼ばれるので注意!
    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        if (_material == null && Renderer != null) {
            _material = new Material(Renderer.sharedMaterial);
            Renderer.sharedMaterial = _material;
        }
        if (_material == null) {
            return;
        }
        var progress = (float)(playable.GetTime() / playable.GetDuration());
        _material.color = Color.Lerp(StartColor, EndColor, progress);
    }
}

PlayableBehaviourにはフレームごとの処理を定義します。

一点注意が必要なのが、Timelineは非ランタイムでも呼ばれるということです。
非ランタイムで呼ばれても問題ないような書き方をする必要があります(上記の例はちょっと適当ですが)。

次にPlayableAssetを継承したクラスを作ります。

using UnityEngine;
using UnityEngine.Playables;

public class ExamplePlayableAsset : PlayableAsset
{
    [SerializeField]
    private ExposedReference<Renderer> _renderer;
    [SerializeField]
    private Color _startColor;
    [SerializeField]
    private Color _endColor;

    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    {
        // PlayableBehaviourを元にPlayableを作る
        var playable = ScriptPlayable<ExamplePlayableBehaviour>.Create(graph);
        // PlayableBehaviourを取得する
        var behaviour = playable.GetBehaviour();
        // 参照を解決する
        behaviour.Renderer = _renderer.Resolve(graph.GetResolver());

        behaviour.StartColor = _startColor;
        behaviour.EndColor = _endColor;

        return playable;
    }
}

PlayableAssetはTimeline上の1つのクリップ情報を表すものです。
先ほど作ったPlayableをインスタンス化して返すメソッドを持ちます。

これでPlayable TrackのメニューにAdd Example Playable Assetが追加されるのでこれを選択します。

f:id:halya_11:20190326140456p:plain

こんな感じで色を変更するクリップが作れました。

f:id:halya_11:20190326140522g:plain

カスタムトラックから作ればブレンドも可能に

最後に紹介するのがトラックからカスタムする方法です。
この方法は最も自由度が高く、重なったクリップ同士をブレンドしたりもできます。

ただしその分定義するクラスも多くなります。
そのためこの方法の詳細は別の記事としてまとめていますのでこちらをご覧ください。

light11.hatenadiary.com

参考サイト

www.youtube.com

関連

light11.hatenadiary.com

light11.hatenadiary.com

light11.hatenadiary.com