yotiky Tech Blog

とあるエンジニアの備忘録

Unity - Timeline 解体新書

Timelineについての覚書です。

TL;DR

  • 図を使い全体像を俯瞰的に把握することでTimelineのシルエットを掴む。
  • 具体的な使い方とか実装方法は含まない。
  • カスタムトラックは関連性を図示し、Default Playables のWizardで生成されるコードとサンプルプロジェクトで使用していたTipsを埋め込んだサンプルコードを記載。
  • Webから入手可能なTimelineの機能拡張を含むサンプルプロジェクトや情報の紹介。
  • 付録にオブジェクトの情報をダンプしたログを記載。

目次

環境

  • Unity 2019.4.25f1
  • Timeline 1.6.3
  • Default Playables 1.8.0

※公式ドキュメントへのリンクは、バージョンによってページがあったりなかったりするので、飛び先のバージョンがバラバラなのは注意してほしい。

Timeline の概要

Playables API

そもそもは Playables API が存在する。 Playables API は PlayableGraph というツリー構造のデータソースを構築し再生することができる。 アニメーションやオーディオ、スクリプトをサポートしており、AnimationControllerの内部でも利用されているLowLevelなAPI群。 複数のデータソースをミックスしたりブレンドしたりもできる。 構築した内容は時系列で(フレーム毎に)出力される状態が評価され、再生することで連続的に状態が変化して動きを生む。

Playable API - Unity マニュアル

PlayableGraph Visualizer

PlayabGraph はグラフを可視化する PlayableGraph Visualizer というパッケージが提供されている。 導入するとWindowはAnalysisから開けるようになる。

f:id:yotiky:20220210225248p:plain:w300f:id:yotiky:20220211070802p:plain:w300

About PlayableGraph Visualizer | Package Manager UI website

f:id:yotiky:20220210224103p:plain

PlayableGraph Visualizerでは、IPlayable、IPlayableOutput、IPlayableBehaviourなオブジェクトがノードとして表示される。 上の図では、ScriptOutputがIPlayableOutput、TimelineとActivationMixerがIPlayableBehaviour、PlayableがIPlayableなオブジェクトである。

f:id:yotiky:20220211072036p:plain:w300

PlayableGraph Visualizerは、Timelineから複数のPlayableOutputを出力するように描画できないため、TimelineのTrackが増えるとTrackの数だけ複製して描画されるようになる。 Timelineから右は再生中の動きも含め全部同じであり、左端のPlayableOutputだけがTrack毎に定義される。 このグラフ自体はスクロールや拡大縮小などできないため、複数描画されてツリーが小さく表示されるとノードが見えなくなるし、ノードをクリックするのも困難になるので参考程度にしか使えない。

Timeline

Timeline は PlayableGraph をエディタで視覚的に作成、編集できるようにした仕組み。 Timeline エディタで時系列に状態を定義することができ、定義した内容を永続化してくれる。 Timeline 自体は ScriptableObject でアセットとして保存されるので、Sceneで利用する時はバインディングを使ってGameObjectと関連付けられる。そのため、バインディング内容を変更するなど再利用が可能である。 また、機能を拡張するための機構も用意されている。

f:id:yotiky:20220210231907p:plain

タイムラインの概要 - Unity マニュアル

標準機能

Timeline では以下の機能が用意されている。

Track

  • ActivationTrack
    • BindingType:GameObject
    • Clip:ActivationClip
    • GameObject のアクティブ状態を制御する
  • AnimationTrack
    • BindingType:Animator
    • Clip:AnimationClip
    • Animator のアニメーションを再生する
  • AudioTrack
    • BindingType:AudioSource
    • Clip:AudioCilp
    • AudioClip を再生する
  • ControlTrack
    • BindingType:-
    • Clip:(ControlPlayableAsset)
      • Activation
      • Prefabのインスタンス
      • PlayableDirector
      • ParticleSystem
      • ITimeControl
        • 最も単純な拡張機構
        • ClipのPlay中に毎フレーム呼ばれる
        • Clipの開始時間やDurationなどの情報が取れないのでただ毎フレーム処理するだけ
    • GameObjectの時間に関連する要素を制御する
  • PlayableTrack
    • BindingType:-
    • Clip:カスタムクリップ
    • カスタムクリップを再生する
      • カスタムクリップを作成し再生することができる拡張機構
      • カスタムトラックでTrackClipTypeを指定されているカスタムクリップは除外される
  • SignalTrack
    • BindingType:SignalReceiver
    • Clip : Signal / Marker
    • バインディングされたレシーバーに信号を送信する
  • GroupTrack
    • BindingType:-
    • Clip : Track
    • Trackを階層的に並べられるコンテナ

Marker

  • Signal
    • SignalをSignalReceiverに紐付けて処理を呼び出せる
    • 1つのReceiverは、1つのSignalに1つの処理を紐付けられる
    • 呼び出す処理が違う場合はSignalの定義を増やす必要がある
    • Signalはアセット
  • Marker
    • 1つのMarkerの定義で、配置毎にパラメータを設定することができる
    • 拡張機構
    • 作成するには以下の実装が必要
      • Marker, INotification を実装したMarkerクラス
      • INotificationReceiver を実装したReceiverクラス
      • 機能を持たないエディタ上でマークするだけのMarkerであれば INotification とReceiverの実装は不要
    • Webのサンプルにあった例
      • TimeScaleの制御
      • 特定フレームへのジャンプ
      • Timelineエディタ上での注釈

Default Playables

公式が配布しているパッケージ。 Timelineのカスタムトラック一式を作成するためのテンプレートを生成してくれる「Timeline Playables Wizard」とカスタムトラック一式の例が含まれる。

Default Playables | Essentials | Unity Asset Store

Track

  • LightControlTrack
    • BindingType:Light
    • Clip : LightControlClip
    • ライトを制御する
  • NavMeshControlTrack
    • BindingType:NavMeshAgent
    • Clip : NavMeshAgentControlClip
    • NavMeshAgentの宛先を制御する
  • ScreenFaderTrack
    • BindingType:Image
    • Clip : ScreenFaderClip
    • 画像を使ったフェードを制御する
  • TextSwitcherTrack
    • BindingType:Text
    • Clip : TextSwitcherClip
    • テキストを制御する
  • TimeDilationTrack
    • BindingType:-
    • Clip : TimeDilationClip
    • TimeScaleを制御する
  • TransformTweenTrack
    • BindingType:Transform
    • Clip : TransformTweenClip
    • StartとEndに指定したTransform間を移動する
  • VideoScriptPlayableTrack
    • BindingType:-
    • Clip : VideoScriptPlayableAsset
    • VideoPlayer componentを介してビデオを再生する

Cinemachine

Cinemachineのパッケージが入っているとCinemachineの機能が使えるようになる。

Track

  • CinemachineTrack
    • BindingType:CinemachineBrain
    • Clip : CinemachineShot
    • Cinemachineのカメラワークを制御する

機能拡張

Timelineで機能拡張する方法は3つ存在する。

ITimeControl

  • ControlTrack + ITimeControlを実装したComponent
  • 最も単純な拡張機構
  • ClipのPlay中に毎フレーム呼ばれる
  • Clipの開始時間やDurationなどのClip情報が取れないのでただ毎フレーム処理するだけ

カスタムクリップ

  • PlayableTrack + カスタムクリップ
  • カスタムクリップを作成すると再生することができる拡張機構
  • カスタムトラックでTrackClipTypeに指定されているカスタムクリップは除外される
  • 自身のClipの情報を取得できる
  • Clip間にまたがる処理はできない(Weightを使ったブレンドなど)
  • 作成するには以下の実装が必要
    • Clip
      • PlayableAsset, ITimelineClipAsset を実装したClip相当の PlayableAsset クラス
      • PlayableBehaviour を継承したClipの振る舞い相当の PlayableBehaviour クラス
  • Webのサンプルにあった例
    • 動画の字幕

カスタムトラック

  • 独自のTrack、MixerPlayableBehaviour 、Clip、PlayableBehaviourを実装する
  • 作成するには以下の実装が必要
    • Track
      • TrackAsset を継承した Track 相当の TrackAsset クラス
      • PlayableBehaviour を継承したClip間のブレンドを担当する MixerPlayableBehaviour クラス
    • Clip
      • PlayableAsset, ITimelineClipAsset を実装したClip相当の PlayableAsset クラス
      • PlayableBehaviour を継承したClipの振る舞い相当の PlayableBehaviour クラス
  • Webのサンプルにあった例

Timeline エディタ周りのカスタマイズ

参考

Timelneを調べるに当たり参考にしたページ集。 使い方や解説なども含まれるので勉強する際には参考になれば。

yotiky.hatenablog.com

Webのサンプル

Timelineパッケージのサンプル

  • AnnotationMarker
    • ブックマークとして使用できるマーカーを提供します。
  • TextTrack
    • TextMeshProテキストコンポーネントを使用して画面にさまざまなメッセージを表示するために使用できるトラックを提供します。
  • TimeDilation
    • Time.timeScale を調整するために使用できるトラックを提供します。
  • Tween
    • 単純な変換動作に使用できるトラックを提供します。
  • Video
    • ビデオクリップを再生できるトラックを提供します。

Samples | Timeline | 1.6.4

ATerribleKingdom

blog.unity.com

  • AICommand
  • Dialogue
  • Light
  • TimeMachine
  • TMPTextSwitcher

GitHub - ciro-unity/ATerribleKingdom: Scripting the Timeline for games in creative ways. Includes a small RTS game build on the 'A Mighty Kingdom' assets

Danmaku

f:id:yotiky:20220211010931p:plain

  • Dialogue
  • PathWalker

【Unite 2018 Tokyo】Timeline機能拡張:カットシーンにとどまらない新たな使い方

Danmaku Shooter - Timeline Scripting Example.zip - Google ドライブ

Cinemachine-market

f:id:yotiky:20220211010818p:plain

  • ScrollingText
  • TMPTextSwitcher

GitHub - ciro-unity/cinemachine-market: Small demo of some various uses of Cinemachine

TimelineMarkerCustomization

blog.unity.com

  • JumpMarker
  • AnnotationMarker

GitHub - Unity-Technologies/TimelineMarkerCustomization: Examples to show how markers and notifications work.

同人誌

使い方やアイデアなどコードのない事例も含む。

Aiming Teck Book 2

  • エフェクト再生のCustomTrack
  • イベント発生のCutomTrack
  • TimelineCombination : 複数のTimelineを指定したFrameで再生していく機能
  • Muteを使ってアビリティ効果の適用範囲を制御

UniTips 7

  • Clipの文字、警告、Clipのカラー、右クリックメニューなどClipのカスタマイズ

Shallow Dive Timeline

Playables API や Timeline 周りはとにかく混乱しがちで難易度が高い。 いくつか理由を挙げてみる。

  • "Playable"という単語がそこかしこに名付けられていて区別がしづらい
  • 同じクラスを継承するレベルの違うクラス群が入れ子構造になっている
  • 戻り値の型が抽象クラスだったりモノによってはObjectだったりして実体が覚えられない
  • internalとかprivateとかNativeとか、アクセスできない情報が多い

Timeline の概要で説明したように、TimelineとPlaybles API(PlayableGraph)の関係性がまず大前提として知っておくべきことである。 Timeline は PlayableGraph をエディタで視覚的に作成、編集できるようにした仕組みであり、永続化と機能拡張できる機構が備わっている。あくまで実体は PlayableGraph の方にある。

f:id:yotiky:20220211081402p:plain

f:id:yotiky:20220211065046p:plain

クラスの関連図

TimelineとPlaybles APIの主要なクラスの関係性を図示する。

f:id:yotiky:20220211080420p:plain

次に各名前空間の参照関係である。主要なクラスは4つに別けられていて、Playablesにコア機能がありそれぞれ参照する形になる。

f:id:yotiky:20220211061935p:plain

Playable / PlayableOutput

f:id:yotiky:20220211062432p:plain

Playable は PlayableGraph で相互に接続できるノードであり、ノードに接続した子の「重み」または「影響力」などを設定できる。 Playable も PlayableOutput も構造体で、スクリプトでPlayableGraphを辿っても、Graphを構成するための情報くらいしか取れない。取得できる情報の型はPlayableで統一されている。 ScriptPlayable<T>は、PlayableBehaviourを使用して独自のカスタムPlayableを作成するための機能である。

f:id:yotiky:20220211062455p:plain

PlayableOutput は 接続された Playable の出力先。TimelineだとTrackに相当する。 PlayableOutput からは、Timeline層のTrackを表すTrackAssetと、TrackにバインドしたデータであるUserDataを取得することができる。

f:id:yotiky:20220211070802p:plain:w300 f:id:yotiky:20220211065742p:plain:w300

PlayableGraphで見ると、左端のAnimationOutputやScriptOutputがPlayableOutput、Animationの方ではTimelineを除く右3つ、Scriptの方では右端の3つがPlayableとなる。

TimelinePlayableとActivationMixerPlaybleはPlayableBehaviourである。(PlayableBehaviourは後述) ちなみにActivationMixerPlayableはinternalなクラスのため、UnityEngine.Timeline外からは参照できない。

PlayableとPlayableOutputでは、各構造体にではなくExtentionsクラスで機能が拡張されている。

  • PlayableExtensions
  • PlayableOutputExtensions

図に示した名前空間以外に、UnityEngine.Experimental.Playables配下にもPlayableなクラスが用意されている。

  • CameraPlayable
  • MaterialEffectPlayable
  • TextureMixerPlayable
  • TexturePlayableOutput

PlayableBehaviour

f:id:yotiky:20220211071426p:plain

PlayableBehaviour はユーザー定義の動作をPlayableGraphに追加するためのインターフェスおよび基本クラス。 既定ではControlTrackで使われる機能やPlayableGraphで表示されるTimelineなどが備わっている。 CustomTrackを作成する場合は、ブレンドの仕組みを実装するMixerPlaybleBehaviourとClipの振る舞いを実装するPlaybleBehaviourで利用することになる。

Timeline上では、TrackでClip間を監視するMixerPlayableBehaviourとClipのPlayableBehaviourで入れ子構造のイメージが湧く。実際はPlayableBehaviour以外もGraphに接続されるのでより複雑なツリー構造ができあがる。

PlayableAsset

f:id:yotiky:20220211074302p:plain

PlayableAsset はScriptableObjectで、Timelineの設定をアセットに永続化し、実行時にPlayableをインスタンス化するために使用される。

TimelineAssetはTimelineのアセットで1つのTimeline自体を定義し、TrackAssetはTimelineのトラックを定義する。右下のPlayableAssetを継承するクラス群はClipの定義となる。 CustomTrackを作成する場合は、TrackAssetを継承するCustomTrackとPlayableAssetを継承するCustomClipを実装する。 ActivationPlayableAssetはinternalなため、外部からは見えない。

Signal/Marker

f:id:yotiky:20220211075208p:plain

MarkerはScriptableObjectで、設定が永続化される。SignalはSignal自体がアセットである。 CustomMarkerを作成する場合は、Markerを継承したCustomMarkerクラスとINotificationReceiverを実装したCustomReceiverクラスを実装する。

PlayableGraph / PlayableDirector / TimelineClip

f:id:yotiky:20220211075836p:plain

PlayableGraphは素の構造体である。

PlayableDirectorはIExposedPropertyTableを実装している。 これはTimelineのアセットとScene上のGameObjectやComponentの参照関係を解決するための仕組みを提供している。

TimelineClipは、ClipのPlayableAssetをラップしたクラスでTrackのClipを表す。

オブジェクトブラウザー

オブジェクトブラウザーを使って見れるオブジェクトの一覧。

f:id:yotiky:20220211081815p:plain

PlayableDirector

f:id:yotiky:20220211082000p:plain

PlayableDirector から取得できる主なデータはPlayableGraphとPlayableAsset(実体はTimelineAsset)の2つである。

PlayableGraphでは、PlayableOutputを出力先としてツリー状にPlayableの数珠つなぎ構造が見て取れる。 GraphおよびPlayableはTimelineAsset(Timelineエディタ上)とは定義の粒度が違うので注意が必要。 PlayableOutputはTrackと対の関係であり、TrackAssetとTrackにバインドされたデータは取得できる。

PlayableAssetは抽象クラスだが実体はTimelineAssetである。 上でも書いた通りGraphとTimelineAssetで定義の粒度は違う。 TimelineAsset以下はTimelineエディターの粒度である。PlayableGraphはもっと細かい粒度となる。

TimelineAssetから実行時の振る舞い(PlayableBehaviour)をたどることはできない。 PlayableBehaviourはGraph上で呼び出されて自分の処理を全うするのみとなる。

PlayableDirectorでTimeline扱う場合は、Directorの再生開始時にGraphが生成され、終了すると破棄される。 Timelineの設定を元に生成されるGraphは、生成された後は動的に関連付けられておらず、生成後にTrackのミュートなどを行っても生成済みのGraphへは反映されない。 Graphへ反映させるにはRebuildGraphする必要がある。 RebuildGraphはPlayableGraphの処理の中からは実行できない。

ControlTrackでPlayableDirectorを入れ子にした場合、子のTimeやSpeedを変更しても効果はない。 SignalやMarkerを使って別のTimelineとして非同期で起動すれば動作する。

Manual再生

timeUpdateModeをManualに設定すると、シーケンスを自分で更新して進めることが出来る。

PlayableDirectorのtimeを更新してEvaluateを呼ぶとシーケンスが進む。PlayableDirector自体のPlayを呼ぶ必要はない。呼んじゃダメ。 timeはdouble型。doubleなのでframeとは誤差が生じる。Timeline上のあるframeを確実に踏めるか怪しい。 増加方向に前回のtimeと値が近ければスムーズな動きができるが、差が大きければコマが飛ぶ。 もちろん前回のtimeより小さければ巻き戻る。

AudioTrackの音はManualだと鳴らないので自分で仕掛ける必要がある。 あるタイミング(厳密じゃなくある程度のタイミング)で再生はできるが、Frame単位で細かく合わせるのは厳しそう。 この他にSignalやMarkerも発火しないので自分で呼ぶように実装が必要。

これら発火しないものに関しては自分で発火させてるだけなので、Manualから途中でGameTimeに切り替えてPlay続行するようなイレギュラーなことをした場合、発火したことにはなっておらず再度実行される。

ヘッダー領域のMarkerに手動で通知する場合のサンプル。

for (int i = 0; i < director.playableGraph.GetOutputCount(); i++)
{
    var output = director.playableGraph.GetOutput(i);
    var playable = output.GetSourcePlayable().GetInput(i);

    var track = director.playableAsset as TimelineAsset;
    // Timelineのヘッダー領域のMarkerにはTrackが存在しない
    if(output.GetPlayableOutputType() != typeof(ScriptPlayableOutput) || output.GetReferenceObject() != null)
      continue;
    
    foreach (var m in track.markerTrack.GetMarkers().OfType<Marker>())
    {
        if (!(m is INotification)) 
          continue;

        bool fire = (m.time >= oldTime && m.time < time) || (m.time > time && m.time <= oldTime);
        if (fire)
            output.PushNotification(playable, m as INotification);
    }
}

Signal / Marker

Timeline のヘッダー領域とSingalTrackに配置できる。

Retroactive

ONでもOFFでも再生ヘッドが通過した範囲内で過去のSignalで通知が発動していないものがあればPlayのタイミングで発動する。 ONにした場合、再生ヘッドが通過していない範囲の呼ばれていない過去のSginalも発動する。 Manualで自分で通知していた場合はカウントされないので、Modeを切り替えてPlayableDirectorをPlayした場合はPlayのタイミングでも発動するので2度発動することになる。

EmitOnce

OFFの場合通過するたびに発動する。 ONの場合1度発動した後は何度通過しても発動しない。

Group

        var timeline = director.playableAsset as TimelineAsset;
        foreach (var track in timeline.GetRootTracks().OfType<GroupTrack>())
        {
            foreach (var child in track.GetChildTracks())
            {
                this.Log(child.GetGroup().name + "\\" + child.name);
            }
        }

キャストが必要な場面

以下は擬似コード

PlayableDirector.playableAsset as TimelineAsset
PlayableDirector.GetGenericBinding() as TrackのBindingType
PlayableDirector.GetReferenceValue() as ExposedReferenceのBIndingType

TrackAsset.parent as TimelineAsset, GroupTrack, ...

TimelineClip.asset as ControlPlayableAsset, AnimationPlayableAsset, CustomClip, ...

PlayableBinding.sourceObject as ActivationTrack, AnimationTrack, CustomTrack, ...

PlayableGraph.GetResolver() as PlayabledDirector

PlayableOutput.GetReferenceObject() as ActivationTrack, AnimationTrack, CustomTrack, ...
PlayableOutput.GetUserData() as TrackのBindingType

カスタムトラック

Timeline Playables WizardをでGenerateするとカスタムトラックに関連する4つのクラスが生成される。

f:id:yotiky:20220211083149p:plain

TrackとClipの設定の永続化と実行時にPlayableをインスタンス化するCustomTrackとCustomClip。
TrackにまたがってClip間のブレンドなどを処理するCustomMixerBehaviour。
Clip自体の振る舞いを実装するCustomBehaviour。

f:id:yotiky:20220211093052p:plain

TimelineAssetはアセットファイル(.playable)として保存されている。
TrackAssetを継承するCustomTrackはTimelineClipを保持しており、TimelineClipはCustomClipを内包する。
CustomTrackとCustomClipはそれぞれのBehaviourを生成する役割を持つ。

以降、生成される4つのクラスと事例で見つけたTipsを埋め込んだサンプルを掲載する。

CustomTrack

[TrackColor(0.4856768f, 0f, 1f)]
[TrackClipType(typeof(SimpleCustomClip))]
[TrackBindingType(typeof(GameObject))]
public class SimpleCustomTrack : TrackAsset
{
    public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
    {
        var playable = ScriptPlayable<SimpleCustomMixerBehaviour>.Create (graph, inputCount);

        // スクリプトでデータを受け渡しする場合
        // Mixerへ
        var mixerBehaviour = playable.GetBehaviour();
        if (mixerBehaviour != null)
        {
            mixerBehaviour.Label = "Label1";
        }
        // Clipへ
        foreach (var clip in GetClips())
        {
            var asset = clip.asset as SimpleCustomClip;
            if (asset != null)
            {
                asset.ClipInTime = clip.clipIn;
                asset.StartTime = clip.start;
            }
        }

        return playable;
    }

    public override void GatherProperties(PlayableDirector director, IPropertyCollector driver)
    {
#if UNITY_EDITOR
        // TrackにBindingされたオブジェクトを取得
        var trackBinding = director.GetGenericBinding(this) as GameObject;
        if (trackBinding == null) return;

        // EditorでInspectorなどのプロパティを編集するためのSerializedObjectを利用
        var serializedObject = new SerializedObject(trackBinding);
        var iterator = serializedObject.GetIterator();
        while (iterator.NextVisible(true))
        {
            if (iterator.hasVisibleChildren)
                continue;

            driver.AddFromName<Transform>(trackBinding.gameObject, iterator.propertyPath);
        }
#endif
        base.GatherProperties(director, driver);
    }
}

CustomClip

[Serializable]
public class SimpleCustomClip : PlayableAsset, ITimelineClipAsset, IPropertyPreview
{
    public SimpleCustomBehaviour template = new SimpleCustomBehaviour();
    public ExposedReference<Transform> transform;

    public float distance;

    public ClipCaps clipCaps
    {
        get { return ClipCaps.All; }
    }

    public double ClipInTime { get; set; }
    public double StartTime { get; set; }

    public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
    {
        var playable = ScriptPlayable<SimpleCustomBehaviour>.Create(graph, template);
        // Inspectorで設定した内容をBehaviourに反映する
        SimpleCustomBehaviour clone = playable.GetBehaviour();
        clone.transform = transform.Resolve(graph.GetResolver());
        clone.distance = distance;
        return playable;
    }

    public void GatherProperties(PlayableDirector director, IPropertyCollector driver)
    {
        // 再生終了などで状態を元に戻す場合は、IPropertyPreviewを実装する
        var resolved = director.GetReferenceValue(transform.exposedName, out var isValid) as Transform;
        if (isValid)
        {
            driver.AddFromName(resolved, "m_LocalPosition.x");
            driver.AddFromName(resolved, "m_LocalPosition.y");
            driver.AddFromName(resolved, "m_LocalPosition.z");
            driver.AddFromName(resolved, "m_LocalRotation.x");
            driver.AddFromName(resolved, "m_LocalRotation.y");
            driver.AddFromName(resolved, "m_LocalRotation.z");
            driver.AddFromName(resolved, "m_LocalRotation.w");
        }
    }
}

ClipCaps

ClipをTimelineエディタで値に応じた編集ができるようになる。 個々の機能は別途動作するように実装しなければならない。

定義 説明
None すべての機能はサポートされません。
Looping Playable を表すクリップはループをサポートします。
Extrapolation Playable を表すクリップはクリップの補外をサポートします。
ClipIn Playable を表すクリップは 0 より大きい初期ローカル時刻をサポートします。
SpeedMultiplier Playable を表すクリップはタイムスケールをサポートします。
Blending Playable を表すクリップはクリップ間のブレンディングをサポートします。
All すべての機能がサポートされます。

BlendCurves

2つのクリップ間のブレンド、もしくはEaseIn/EaseOutのどちらかに使用される。 BlendInDuration/BlendOutDurationが編集できない時はブレンド、編集できる時はEaseIn/EaseOut。

CustomMixerBehaviour

public class SimpleCustomMixerBehaviour : PlayableBehaviour
{
    private PlayableDirector director;

    public string Label { get; set; }

    public override void OnPlayableCreate(Playable playable)
    {
        // Resolver = PlayableDirector
        director = (playable.GetGraph().GetResolver() as PlayableDirector);
    }

    // NOTE: This function is called at runtime and edit time.  Keep that in mind when setting the values of properties.
    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        // Trackにバインディングされたデータ
        GameObject trackBinding = playerData as GameObject;

        if (!trackBinding)
            return;

        int inputCount = playable.GetInputCount();

        for (int i = 0; i < inputCount; i++)
        {
            float inputWeight = playable.GetInputWeight(i);
            ScriptPlayable<SimpleCustomBehaviour> inputPlayable = (ScriptPlayable<SimpleCustomBehaviour>)playable.GetInput(i);
            SimpleCustomBehaviour input = inputPlayable.GetBehaviour();

            // Use the above variables to process each frame of this playable.
            if (0 < inputWeight)
            {
                // 再生中のClip
            }
        }
    }

    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
        // Trackで変更されたデータを元の状態に戻したりする
    }

    public override void OnGraphStop(Playable playable)
    {
        // Trackで変更されたデータを元の状態に戻したりする
    }

    public override void OnPlayableDestroy(Playable playable)
    {
        // Trackで変更されたデータを元の状態に戻したりする
    }
}
関数 説明
OnGraphStart この関数は、このPlayableBehaviourを所有するPlayableGraphが起動したときに呼び出されます。
OnGraphStop この関数は、このPlayableBehaviourを所有するPlayableGraphが停止したときに呼び出されます。
OnPlayableCreate この関数は、PlayableBehaviourを所有するPlayableが作成されたときに呼び出されます。
OnPlayableDestroy この関数は、PlayableBehaviourを所有するPlayableが破棄されたときに呼び出されます。
OnBehaviourPause このメソッドは、次のいずれかの状況が発生したときに呼び出されます。トラバーサル中の有効な再生状態がPlayState.Pausedに変更された場合。この状態は、FrameData.effectivePlayStateによって示されます。PlayableGraphは、再生可能な再生状態がPlayingである間は停止します。この状態は、PlayableGraph.IsPlayingがtrueを返すことで示されます。
OnBehaviourPlay この関数は、Playableの再生状態がPlayState.Playingに変更されたときに呼び出されます。
PrepareData この関数は、PlayableGraphのPrepareDataフェーズで呼び出されます。
PrepareFrame この関数は、PlayableGraphのPrepareFrameフェーズで呼び出されます。
ProcessFrame この関数は、PlayableGraphのProcessFrameフェーズ中に呼び出されます。

CustomBehaviour

[Serializable]
public class SimpleCustomBehaviour : PlayableBehaviour
{
    public Transform transform;
    public float distance;

    private string Name => nameof(SimpleCustomBehaviour);

    public override void OnGraphStart(Playable playable)
    {
        Debug.LogFormat("{0} start: {1}", Time.frameCount, Name);
    }

    public override void OnGraphStop(Playable playable)
    {
        Debug.LogFormat("{0} stop: {1}", Time.frameCount, Name);
    }

    public override void OnBehaviourPlay(Playable playable, FrameData info)
    {
        Debug.LogFormat("{0} play: {1}", Time.frameCount, Name);
    }

    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
        Debug.LogFormat("{0} pause: {1}", Time.frameCount, Name);
    }

    public override void OnPlayableCreate(Playable playable)
    {
        Debug.LogFormat("{0} create: {1}", Time.frameCount, Name);
    }

    public override void OnPlayableDestroy(Playable playable)
    {
        Debug.LogFormat("{0} destroy: {1}", Time.frameCount, Name);
    }

    public override void PrepareFrame(Playable playable, FrameData info)
    {
        Debug.LogFormat("{0} prepare: {1}", Time.frameCount, Name);
    }

    public override void ProcessFrame(Playable playable, FrameData info, object playerData)
    {
        Debug.LogFormat("{0} process: {1}", Time.frameCount, Name);

        // Trackにバインディングされたデータ
        GameObject trackBinding = playerData as GameObject;

        // Clipの進捗を取る
        var progress = (float)(playable.GetTime() / playable.GetDuration());
    }
}
関数 説明
OnGraphStart この関数は、このPlayableBehaviourを所有するPlayableGraphが起動したときに呼び出されます。
OnGraphStop この関数は、このPlayableBehaviourを所有するPlayableGraphが停止したときに呼び出されます。
OnPlayableCreate この関数は、PlayableBehaviourを所有するPlayableが作成されたときに呼び出されます。
OnPlayableDestroy この関数は、PlayableBehaviourを所有するPlayableが破棄されたときに呼び出されます。
OnBehaviourPause このメソッドは、次のいずれかの状況が発生したときに呼び出されます。トラバーサル中の有効な再生状態がPlayState.Pausedに変更された場合。この状態は、FrameData.effectivePlayStateによって示されます。PlayableGraphは、再生可能な再生状態がPlayingである間は停止します。この状態は、PlayableGraph.IsPlayingがtrueを返すことで示されます。
OnBehaviourPlay この関数は、Playableの再生状態がPlayState.Playingに変更されたときに呼び出されます。
PrepareData この関数は、PlayableGraphのPrepareDataフェーズで呼び出されます。
PrepareFrame この関数は、PlayableGraphのPrepareFrameフェーズで呼び出されます。
ProcessFrame この関数は、PlayableGraphのProcessFrameフェーズ中に呼び出されます。

ExposedReference<T>

Timelineはアセットであるため、Scene上のオブジェクトを直接参照できない。 PlayableDirectorではこれを解決するためにExposedReference<T>IExposedPropertyTableを利用して参照関係を構築している。PlayableDirectorはIExposedPropertyTableを実装している。

Scene上のGameObjectを参照するClipは、ExposedReference<T>でメンバを公開する。

    [Serializable]
    public class Sample01PlayerClip : PlayableAsset, ITimelineClipAsset
    {
        // 一部抜粋
        public ExposedReference<PlayableDirector> director;

        public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
        {
            var playable = ScriptPlayable.Create(graph, template);
            Sample01PlayerBehaviour clone = playable.GetBehaviour();
            clone.clipName = clipName;
            clone.director = director.Resolve(graph.GetResolver());

            return playable;
        }
    }

ExposedReference<T>は次のようになっている。

    [Serializable]
    [UsedByNativeCode(Name = "ExposedReference")]
    public struct ExposedReference<T> where T : Object
    {
        [SerializeField]
        public PropertyName exposedName;


        [SerializeField]
        public Object defaultValue;


        public T Resolve(IExposedPropertyTable resolver)
        {
            if (resolver != null)
            {
                bool idValid;
                Object referenceValue = resolver.GetReferenceValue(exposedName, out idValid);
                if (idValid)
                {
                    return referenceValue as T;
                }
            }


            return defaultValue as T;
        }
    }

f:id:yotiky:20220211100650p:plain

Timeline上でClipにオブジェクトを設定すると内部でexposedNameが発行される。 PlayableDirectorの設定でExposedReferenceのnameとオブジェクトのfileIDがテーブルに保持される。 exposedNameの自動発行は融通が効かないらしいという書き込みも見られる。 実際、TimelineやHierarchyを操作していると設定していた内容の参照関係が壊れて設定欄が赤くなっていることはあった。

付録1

図表全体

f:id:yotiky:20220211102446p:plain

付録2

PlayableDirector から辿れる情報(クラス定義や実際の値)をログに出力した結果を貼っておく。

実行時のTimelineは次の通り。

f:id:yotiky:20220211093836p:plain:w600

f:id:yotiky:20220211093855p:plain:w450f:id:yotiky:20220211093917p:plain:w160

f:id:yotiky:20220211094027p:plain:w300

PlayableDirector

        /*
        duration   再生可能時間(秒単位)。
        extrapolationMode  再生可能期間を超えたときに時間をインクリメントする方法を制御します。
        initialTime    Playableが最初にプレイされたときに開始する時間。
        playableAsset  再生用に再生可能オブジェクトをインスタンス化するために使用されるPlayableAsset。
        playableGraph  PlayableDirectorによって作成されたPlayableGraph。
        playOnAwake    コンポーネントが起動するとすぐに再生可能なアセットの再生が開始されるかどうか。
        state  コンポーネントの現在の再生状態。(読み取り専用)
        time   コンポーネントの現在の時刻。この値は、再生中にPlayableDirector.timeUpdateModeに従ってインクリメントされます。この値を手動で変更することもできます。
        timeUpdateMode 再生時に時間をインクリメントする方法を制御します。

        ClearGenericBinding    参照オブジェクトのバインディングをクリアします。
        ClearReferenceValue    公開された参照値をクリアします。
        DeferredEvaluate   PlayableDirectorに、次の更新でPlayableGraphを評価するように指示します。
        Evaluate   現在再生中のPlayableを現在評価します。
        GetGenericBinding  参照オブジェクトへのバインディングを返します。
        GetReferenceValue  ExposedReferenceバインディングを取得します。
        Pause  現在実行中の再生可能ファイルの再生を一時停止します。
        Play   提供されたPlayableAssetを使用してPlayableをインスタンス化し、再生を開始します。
        RebindPlayableGraphOutputs PlayableGraphの各PlayableOutputを再バインドします。
        RebuildGraph   既存のPlayableGraphを破棄し、新しいインスタンスを作成します。
        Resume 一時停止した再生可能ファイルの再生を再開します。
        SetGenericBinding  PlayableBindingからの参照オブジェクトのバインディングを設定します。
        SetReferenceValue  ExposedReference値を設定します。
        Stop   現在のPlayableの再生を停止し、対応するグラフを破棄します。

        paused PlayableDirectorコンポーネントが一時停止したときに発生するイベント。
        played PlayableDirectorコンポーネントの再生が開始されたときに発生するイベント。
        stopped    PlayableDirectorコンポーネントが停止したときに発生するイベント。

[director]
name: RootDirector
duration: 201.980666666666
extrapolationMode: None
initialTime: 0
playableAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
playableGraph: UnityEngine.Playables.PlayableGraph
playOnAwake: False
state: Paused
time: 0
timeUpdateMode: GameTime
GetGenericBinding(activationTrack): Cube (UnityEngine.GameObject)
GetReferenceValue.GetReferenceValue(controlAsset.sourceGameObject.exposedName, out bool _): ChildDirector (UnityEngine.GameObject)
         */

playableGraph

PlayableDirector.playableGraph

型:PlayableGraph

/*
        Connect 2つのPlayableインスタンスを接続します。
        Destroy グラフを破棄します。
        DestroyOutput PlayableOutputを破棄します。
        DestroyPlayable Playableを破壊します。
        DestroySubgraph Playableとそのすべての入力を再帰的に破棄します。
        Disconnect Playableを切断します。接続によって、PlayableGraphのトポロジとその評価方法が決まります。
        Evaluate グラフ内のすべてのPlayableOutputsを評価し、グラフ内の接続されているすべてのPlayablesを更新します。
        GetEditorName PlayableGraphの名前を返します。
        GetOutput グラフ内の指定されたインデックスでPlayableOutputを取得します。
        GetOutputByType グラフ内の指定されたインデックスで、要求されたタイプのPlayableOutputを取得します。
        GetOutputCount グラフ内のPlayableOutputの数を返します。
        GetOutputCountByType グラフで要求されたタイプのPlayableOutputの数を取得します。
        GetPlayableCount グラフが所有するPlayableの数を返します。
        GetResolver ExposedReferencesを解決するためにグラフで使用されるテーブルを返します。
        GetRootPlayable 指定されたインデックスに出力接続のないPlayableを返します。
        GetRootPlayableCount 出力が接続されていない、グラフが所有するPlayableの数を返します。
        GetTimeUpdateMode 再生時に時間がどのようにインクリメントされるかを返します。
        IsDone グラフが操作を完了したことを示します。
        IsPlaying グラフが現在実行中であることを示します。
        IsValid PlayableGraphがPlayableGraph.CreateGraphを使用して適切に構築され、削除されていない場合はtrueを返します。
        Play グラフを再生します。
        SetResolver ExposedReferencesを解決するためにグラフで使用されるテーブルを変更します。
        SetTimeUpdateMode 再生時の時間の増分方法を変更します。
        Stop 再生中の場合、グラフを停止します。


[playableGraph]
GetEditorName: RootDirector.PlayableDirector
GetOutputCount: 9
GetPlayableCount: 28
GetRootPlayableCount: 1
IsDone: False
IsPlaying: False
IsValid: True
         */

PlayableDirector.playableGraph.GetRootPlayable(0)

型:Playable

/*
        AddInput 新しい入力ポートを作成し、指定されたPlayableの出力ポートに接続します。
        ConnectInput Playableの出力ポートを入力ポートの1つに接続します。
        Destroy 現在のPlayableを破棄します。
        DisconnectInput Playableの入力ポートを外します。
        GetDuration Playableの継続時間を返します。
        GetGraph このPlayableを所有するPlayableGraphを返します。Playableは、それを作成するために使用されたグラフでのみ使用できます。
        GetInput 指定された入力ポートインデックスに接続されているPlayableを返します。
        GetInputCount Playableでサポートされている入力の数を返します。
        GetInputWeight 指定された入力ポートインデックスに接続されているPlayableの重みを返します。
        GetLeadTime 再生可能なリードタイムを秒単位で返します。
        GetOutput 指定された出力ポートインデックスに接続されているPlayableを返します。
        GetOutputCount Playableでサポートされている出力の数を返します。
        GetPlayState Playableの現在のPlayStateを返します。
        GetPreviousTime Playableの前の現地時間を返します。
        GetPropagateSetTime このPlayableの時間伝播動作を返します。
        GetSpeed 現在のPlayableに適用されている速度乗数を返します。
        GetTime Playableの現在の現地時間を返します。
        GetTraversalMode マルチ出力再生可能の伝播モードを返します。
        IsDone 再生可能オブジェクトが操作を完了したことを示すフラグを返します。
        IsNull Playableがnullの場合はtrueを返し、それ以外の場合はfalseを返します。
        IsValid 現在のPlayableの値を返します。
        Pause Playableを一時停止するように指示します。
        Play Playableの再生を開始します。
        SetDone 再生可能オブジェクトが操作を完了したことを示すフラグを変更します。
        SetDuration Playableの継続時間を変更します。
        SetInputCount Playableでサポートされる入力の数を変更します。
        SetInputWeight 現在のPlayableに接続されているPlayableの重みを変更します。
        SetLeadTime 再生可能なリードタイムを秒単位で設定します。
        SetOutputCount Playableでサポートされる出力の数を変更します。
        SetPropagateSetTime このPlayableの時間伝播動作を変更します。
        SetSpeed 現在のPlayableに適用されている速度乗数を変更します。
        SetTime Playableの現在の現地時間を変更します。
        SetTraversalMode マルチ出力再生可能のPrepareFrameとProcessFrameの伝播モードを設定します。


[rootPlayable]
GetPlayableType: UnityEngine.Timeline.TimelinePlayable
GetDuration: 201.980666666666
GetGraph: UnityEngine.Playables.PlayableGraph
GetInputCount: 9
GetOutputCount: 1
GetLeadTime: 0
GetPlayState: Playing
GetPreviousTime: 0
GetPropagateSetTime: True
GetSpeed: 1
GetTime: 0
GetTraversalMode: Passthrough
         */

PlayableDirector.playableGraph.GetOutput(i)

型:PlayableOutput

/*
            GetPlayableOutputType: Trackと対になるPlayableOutput型 ex)ScriptPlayableOutput
            GetReferenceObject: Trackの実体 ex)ControlTrack
            GetSourceOutputPort ソースプレイアブルの出力接続インデックスを返します。 Graphの接続ポート
            GetSourcePlayable 再生可能なソースを返します。
            GetNotificationReceivers 出力に現在登録されている通知受信者のリストを取得します。 Signal/MarkerのTrackで参照しているReceiver
            GetUserData 不透明なユーザーデータを返します。これは、ProcessFrameの最後の最後の引数と同じ値です。 TrackにバインドされているComponent
            GetWeight PlayableOutputから再生可能なソースへの接続の重みを返します。
            AddNotificationReceiver 通知をリッスンする新しいレシーバーを登録します。
            IsOutputNull PlayableOutputがnullの場合はtrueを返し、そうでない場合はfalseを返します。
            IsOutputValid
            PushNotification Playableシステムを介して送信される通知をキューに入れます。
            RemoveNotificationReceiver 出力のレシーバーの登録を解除します。
            SetReferenceObject バインドされたオブジェクトを新しい値に設定します。出力をオブジェクトに関連付けるために使用されます(タイムラインの場合はアセットを追跡します)。
            SetSourcePlayable 出力を計算する再生可能オブジェクトとサブツリーインデックスを設定します。
            SetUserData 不透明なユーザーデータを設定します。これと同じデータが最後の引数としてProcessFrameに渡されます。
            SetWeight PlayableOutputから再生可能なソースへの接続の重みを設定します。


[playableOutput]
GetPlayableOutputType: UnityEngine.Playables.ScriptPlayableOutput
GetReferenceObject: 
GetSourceOutputPort: 0
GetSourcePlayable: UnityEngine.Playables.Playable
GetNotificationReceivers: 1
GetUserData: RootDirector (UnityEngine.PlayableDirector)
GetWeight: 1
GetNotificationReceivers: RootDirector


[playableOutput]
GetPlayableOutputType: UnityEngine.Playables.ScriptPlayableOutput
GetReferenceObject: Activation Track 1 (UnityEngine.Timeline.ActivationTrack)
GetSourceOutputPort: 1
GetSourcePlayable: UnityEngine.Playables.Playable
GetNotificationReceivers: 0
GetUserData: Cube (UnityEngine.GameObject)
GetWeight: 1


[playableOutput]
GetPlayableOutputType: UnityEngine.Animations.AnimationPlayableOutput
GetReferenceObject: Animation Track 1 (UnityEngine.Timeline.AnimationTrack)
GetSourceOutputPort: 2
GetSourcePlayable: UnityEngine.Playables.Playable
GetNotificationReceivers: 0
GetUserData: 
GetWeight: 0


[playableOutput]
GetPlayableOutputType: UnityEngine.Audio.AudioPlayableOutput
GetReferenceObject: Audio Track 1 (UnityEngine.Timeline.AudioTrack)
GetSourceOutputPort: 3
GetSourcePlayable: UnityEngine.Playables.Playable
GetNotificationReceivers: 0
GetUserData: 
GetWeight: 1


[playableOutput]
GetPlayableOutputType: UnityEngine.Playables.ScriptPlayableOutput
GetReferenceObject: Control Track 1 (UnityEngine.Timeline.ControlTrack)
GetSourceOutputPort: 4
GetSourcePlayable: UnityEngine.Playables.Playable
GetNotificationReceivers: 0
GetUserData: 
GetWeight: 1


[playableOutput]
GetPlayableOutputType: UnityEngine.Playables.ScriptPlayableOutput
GetReferenceObject: Signal Track (UnityEngine.Timeline.SignalTrack)
GetSourceOutputPort: 5
GetSourcePlayable: UnityEngine.Playables.Playable
GetNotificationReceivers: 1
GetUserData: RootDirector (UnityEngine.Timeline.SignalReceiver)
GetWeight: 1
GetNotificationReceivers: RootDirector


[playableOutput]
GetPlayableOutputType: UnityEngine.Playables.ScriptPlayableOutput
GetReferenceObject: Playable Track (UnityEngine.Timeline.PlayableTrack)
GetSourceOutputPort: 6
GetSourcePlayable: UnityEngine.Playables.Playable
GetNotificationReceivers: 0
GetUserData: 
GetWeight: 1


[playableOutput]
GetPlayableOutputType: UnityEngine.Playables.ScriptPlayableOutput
GetReferenceObject: G1-Activation Track (UnityEngine.Timeline.ActivationTrack)
GetSourceOutputPort: 7
GetSourcePlayable: UnityEngine.Playables.Playable
GetNotificationReceivers: 0
GetUserData: Cube (4) (UnityEngine.GameObject)
GetWeight: 1


[playableOutput]
GetPlayableOutputType: UnityEngine.Animations.AnimationPlayableOutput
GetReferenceObject: G1-Animation Track (UnityEngine.Timeline.AnimationTrack)
GetSourceOutputPort: 8
GetSourcePlayable: UnityEngine.Playables.Playable
GetNotificationReceivers: 0
GetUserData: 
GetWeight: 0
            */

PlayableDirector.playableGraph.GetOutput(i).GetSourcePlayable()

型:Playable

/*
        AddInput 新しい入力ポートを作成し、指定されたPlayableの出力ポートに接続します。
        ConnectInput Playableの出力ポートを入力ポートの1つに接続します。
        Destroy 現在のPlayableを破棄します。
        DisconnectInput Playableの入力ポートを外します。
        GetDuration Playableの継続時間を返します。
        GetGraph このPlayableを所有するPlayableGraphを返します。Playableは、それを作成するために使用されたグラフでのみ使用できます。
        GetInput 指定された入力ポートインデックスに接続されているPlayableを返します。
        GetInputCount Playableでサポートされている入力の数を返します。
        GetInputWeight 指定された入力ポートインデックスに接続されているPlayableの重みを返します。
        GetLeadTime 再生可能なリードタイムを秒単位で返します。
        GetOutput 指定された出力ポートインデックスに接続されているPlayableを返します。
        GetOutputCount Playableでサポートされている出力の数を返します。
        GetPlayState Playableの現在のPlayStateを返します。
        GetPreviousTime Playableの前の現地時間を返します。
        GetPropagateSetTime このPlayableの時間伝播動作を返します。
        GetSpeed 現在のPlayableに適用されている速度乗数を返します。
        GetTime Playableの現在の現地時間を返します。
        GetTraversalMode マルチ出力再生可能の伝播モードを返します。
        IsDone 再生可能オブジェクトが操作を完了したことを示すフラグを返します。
        IsNull Playableがnullの場合はtrueを返し、それ以外の場合はfalseを返します。
        IsValid 現在のPlayableの値を返します。
        Pause Playableを一時停止するように指示します。
        Play Playableの再生を開始します。
        SetDone 再生可能オブジェクトが操作を完了したことを示すフラグを変更します。
        SetDuration Playableの継続時間を変更します。
        SetInputCount Playableでサポートされる入力の数を変更します。
        SetInputWeight 現在のPlayableに接続されているPlayableの重みを変更します。
        SetLeadTime 再生可能なリードタイムを秒単位で設定します。
        SetOutputCount Playableでサポートされる出力の数を変更します。
        SetPropagateSetTime このPlayableの時間伝播動作を変更します。
        SetSpeed 現在のPlayableに適用されている速度乗数を変更します。
        SetTime Playableの現在の現地時間を変更します。
        SetTraversalMode マルチ出力再生可能のPrepareFrameとProcessFrameの伝播モードを設定します。

   // 取得するPlayableはすべて同じTimelinePlayable=RootPlayable

[outputPlayables]
GetPlayableType: UnityEngine.Timeline.TimelinePlayable
GetDuration: 201.980666666666
GetGraph: UnityEngine.Playables.PlayableGraph
GetInputCount: 9
GetInput: UnityEngine.Playables.Playable
GetInputWeight: 1
GetOutputCount: 1
GetOutput: UnityEngine.Playables.Playable
GetLeadTime: 0
GetPlayState: Playing
GetPreviousTime: 0
GetPropagateSetTime: True
GetSpeed: 1
GetTime: 0
GetTraversalMode: Passthrough
         */

PlayableDirector.playableGraph.GetOutput(i).GetSourcePlayable().GetInput(i)

型:Playable

/*
[inputPlayable]
GetPlayableType: UnityEngine.Timeline.TimeNotificationBehaviour
GetDuration: 201.980666666666
GetGraph: UnityEngine.Playables.PlayableGraph
GetInputCount: 0
GetOutputCount: 1
GetLeadTime: 0
GetPlayState: Playing
GetPreviousTime: 0
GetPropagateSetTime: True
GetSpeed: 1
GetTime: 0
GetTraversalMode: Mix


[inputPlayable]
GetPlayableType: UnityEngine.Timeline.ActivationMixerPlayable
GetDuration: 1.79769313486232E+308
GetGraph: UnityEngine.Playables.PlayableGraph
GetInputCount: 3
GetOutputCount: 1
GetLeadTime: 0
GetPlayState: Playing
GetPreviousTime: 0
GetPropagateSetTime: False
GetSpeed: 1
GetTime: 0
GetTraversalMode: Mix


[inputPlayable]
GetPlayableType: UnityEngine.Animations.AnimationLayerMixerPlayable
GetDuration: 1.79769313486232E+308
GetGraph: UnityEngine.Playables.PlayableGraph
GetInputCount: 1
GetOutputCount: 1
GetLeadTime: 0
GetPlayState: Playing
GetPreviousTime: 0
GetPropagateSetTime: False
GetSpeed: 1
GetTime: 0
GetTraversalMode: Mix


[inputPlayable]
GetPlayableType: UnityEngine.Audio.AudioMixerPlayable
GetDuration: 1.79769313486232E+308
GetGraph: UnityEngine.Playables.PlayableGraph
GetInputCount: 2
GetOutputCount: 1
GetLeadTime: 0
GetPlayState: Playing
GetPreviousTime: 0
GetPropagateSetTime: False
GetSpeed: 1
GetTime: 0
GetTraversalMode: Mix


[inputPlayable]
GetPlayableType: UnityEngine.Playables.Playable
GetDuration: 1.79769313486232E+308
GetGraph: UnityEngine.Playables.PlayableGraph
GetInputCount: 1
GetOutputCount: 1
GetLeadTime: 0
GetPlayState: Playing
GetPreviousTime: 0
GetPropagateSetTime: False
GetSpeed: 1
GetTime: 0
GetTraversalMode: Mix


[inputPlayable]
GetPlayableType: UnityEngine.Timeline.TimeNotificationBehaviour
GetDuration: 201.980666666666
GetGraph: UnityEngine.Playables.PlayableGraph
GetInputCount: 0
GetOutputCount: 1
GetLeadTime: 0
GetPlayState: Playing
GetPreviousTime: 0
GetPropagateSetTime: True
GetSpeed: 1
GetTime: 0
GetTraversalMode: Mix


[inputPlayable]
GetPlayableType: UnityEngine.Playables.Playable
GetDuration: 1.79769313486232E+308
GetGraph: UnityEngine.Playables.PlayableGraph
GetInputCount: 1
GetOutputCount: 1
GetLeadTime: 0
GetPlayState: Playing
GetPreviousTime: 0
GetPropagateSetTime: False
GetSpeed: 1
GetTime: 0
GetTraversalMode: Mix


[inputPlayable]
GetPlayableType: UnityEngine.Timeline.ActivationMixerPlayable
GetDuration: 1.79769313486232E+308
GetGraph: UnityEngine.Playables.PlayableGraph
GetInputCount: 2
GetOutputCount: 1
GetLeadTime: 0
GetPlayState: Playing
GetPreviousTime: 0
GetPropagateSetTime: False
GetSpeed: 1
GetTime: 0
GetTraversalMode: Mix


[inputPlayable]
GetPlayableType: UnityEngine.Animations.AnimationMotionXToDeltaPlayable
GetDuration: 1.79769313486232E+308
GetGraph: UnityEngine.Playables.PlayableGraph
GetInputCount: 1
GetOutputCount: 1
GetLeadTime: 0
GetPlayState: Playing
GetPreviousTime: 0
GetPropagateSetTime: False
GetSpeed: 1
GetTime: 0
GetTraversalMode: Mix
             */

PlayableDirector.playableGraph.GetOutput(i).GetReferenceObject()

型:Object (TrackAsset)

/*
            TrackAsset
            isEmpty このトラックにクリップが含まれているか。
            isSubTrack このトラックはサブトラックか。
            locked The local locked state of the track.
            lockedInHierarchy The locked state of a track. (Read Only)
            muted トラックをミュートし、作成した PlayableGraph から除外します。
            outputs インスタンス化した Playable の出力の説明。
            parent トラックの所有者。 Group配下の場合はGroupTrack、トップレベルの場合はTimelineAsset
            timelineAsset このトラックが属する TimelineAsset。 保存されているTimelineAsset
            CreateClip Creates a clip on the track with a custom playable asset attached, whose type is specified by T. Throws an InvalidOperationException if the specified type is not supported by the track.
            CreateDefaultClip トラックのデフォルトクリップを作成します。クリップのアセット種類はそのトラックを作成する TrackClipTypeAttribute に基づきます。
            CreateTrackMixer トラックのクリップによって生成された Playable のブレンドに使用するミキサーを作成します。
            GetChildTracks サブトラック、または、トラックに設定された子トラックのリスト。
            GetClips トラックが所有するクリップのリストを返します。


            TimelineClip
            animationClip アニメーション化したパラメーターを含む AnimationClip。
            asset シリアライズ可能な IPlayableAsset への参照で、クリップの特殊性を示します。 PlayableAsset
            clipCaps このクリップがサポートする主な機能。
            clipIn クリップの再生を開始する時刻。
            duration クリップの長さ (秒)。
            end クリップの終了時刻。
            extrapolatedDuration 補外部分も含むクリップの長さ。
            extrapolatedStart 補外部分も含むクリップの開始時刻。
            hasBlendIn クリップにブレンドインがあるか。
            hasBlendOut クリップに、0 以外のブレンドアウトがあるか。
            hasPostExtrapolation クリップの終了時以降に補外があるか。
            hasPreExtrapolation クリップの開始時以前に補外があるか。
            parentTrack Returns the parent track where this clip is attached.
            postExtrapolationMode クリップの終了後のギャップに対する補外モード。
            preExtrapolationMode クリップの開始前のギャップに対する補外モード。
            start クリップの開始時刻。
            timeScale クリップのタイムスケール。
            
            // PlayableAsset
            //var playableAsset = clip.asset as ActivationPlayableAsset; アクセス不可
            //var playableAsset = clip.asset as ControlPlayableAsset;
            //var playableAsset = clip.asset as AudioPlayableAsset;


[track]
name: Activation Track 1
start: 0
end: 6
duration: 6
muted: False
mutedInHierarchy: False
locked: False
lockedInHierarchy: False
parent: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
isSubTrack: False
outputs: UnityEngine.Timeline.TrackAsset+d__70
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)


[clip]
displayName: Active A
start: 0
end: 2
duration: 2
asset: ActivationPlayableAsset (UnityEngine.Timeline.ActivationPlayableAsset)


[clip]
displayName: Active B
start: 2
end: 4
duration: 2
asset: ActivationPlayableAsset(Clone) (UnityEngine.Timeline.ActivationPlayableAsset)


[clip]
displayName: Active C
start: 4
end: 6
duration: 2
asset: ActivationPlayableAsset(Clone)(Clone) (UnityEngine.Timeline.ActivationPlayableAsset)


[track]Animation Track 1
[track]Audio Track 1
[track]Control Track 1


[clip]
displayName: Child
start: 14.464
end: 19.464
duration: 5
asset: ControlPlayableAsset (UnityEngine.Timeline.ControlPlayableAsset)
asset.outputs: 0


[ControlTrack-InputPlayable-0]
GetPlayableType: UnityEngine.Playables.Playable
GetInputCount: 2
GetOutputCount: 1


[ControlTrack-InputPlayable-0-0]
GetPlayableType: UnityEngine.Timeline.ActivationControlPlayable
GetInputCount: 0
GetOutputCount: 1


[ControlTrack-InputPlayable-0-1]
GetPlayableType: UnityEngine.Timeline.DirectorControlPlayable
GetInputCount: 0
GetOutputCount: 1


[track]Signal Track
[track]Playable Track
[ColorTransitionBehaviour]MySamples.Experiment.ColorTransitionBehaviour
[track]
name: G1-Activation Track
start: 0
end: 4
duration: 4
muted: False
mutedInHierarchy: False
locked: False
lockedInHierarchy: False
parent: Group1 (UnityEngine.Timeline.GroupTrack)
isSubTrack: False
outputs: UnityEngine.Timeline.TrackAsset+d__70
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)


[clip]
displayName: Active
start: 0
end: 2
duration: 2
asset: ActivationPlayableAsset (UnityEngine.Timeline.ActivationPlayableAsset)


[clip]
displayName: Active
start: 2
end: 4
duration: 2
asset: ActivationPlayableAsset(Clone) (UnityEngine.Timeline.ActivationPlayableAsset)


[track]G1-Animation Track
             */

playableAsset

PlayableDirector.playableAsset

型:PlayableAsset (TimelineAsset)

/*
        name オブジェクト名
        duration タイムラインの長さ (秒)。
        fixedDuration durationMode を固定の (変化しない) 長さに設定するときの、タイムラインの長さ。
        markerTrack TimelineヘッダーのMarkerTrack
        rootTrackCount タイムラインのルート階層にあるトラックの数を返します。
        outputTrackCount タイムラインの出力トラックの数を返します。
        outputs GetOutputTracks().Select(x => x.outputs.Select(x => x)).SelectMany(x => x) と同等
        GetRootTrack 指定したインデックスのルートトラックを検索します。
        GetRootTracks すべてのルートトラックのリストを取得します。 Markers、GroupTrackを含む。
        GetOutputTrack 指定したインデックスから出力トラックを検索します。
        GetOutputTracks タイムラインのすべての出力トラックのリストを取得します。 Markersを含む。GroupTrackは配下のTrackが展開される。


[timeline]
name: ObjectRelationAnalyTimeline
duration: 201.980666666666
fixedDuration: 0
markerTrack: Markers (UnityEngine.Timeline.MarkerTrack)
rootTrackCount: 9
outputTrackCount: 10
outputs: Markers/Activation Track 1/Animation Track 1/Audio Track 1/Control Track 1/Signal Track/Playable Track/PlayableBehaviour Logger/G1-Activation Track/G1-Animation Track
GetRootTracks: Markers/Group1/Activation Track 1/Animation Track 1/Audio Track 1/Control Track 1/Signal Track/Playable Track/PlayableBehaviour Logger
GetOutputTracks: Markers/Activation Track 1/Animation Track 1/Audio Track 1/Control Track 1/Signal Track/Playable Track/PlayableBehaviour Logger/G1-Activation Track/G1-Animation Track


         */

PlayableDirector.playableAsset.outputs

型:IEnumerable

/*
            streamName 出力または入力ストリームの名前。
            outputTargetType このPlayableBindingのPlayableOutputに必要なターゲットのタイプ。 TrackのTrackBindingType
            sourceObject このバインディングのキーとして機能するUnityEngine.Objectへの参照。 TrackAsset


[binding]
streamName: Markers
outputTargetType: UnityEngine.GameObject
sourceObject: 


[binding]
streamName: Activation Track 1
outputTargetType: UnityEngine.GameObject
sourceObject: Activation Track 1 (UnityEngine.Timeline.ActivationTrack)


[binding]
streamName: Animation Track 1
outputTargetType: UnityEngine.Animator
sourceObject: Animation Track 1 (UnityEngine.Timeline.AnimationTrack)


[binding]
streamName: Audio Track 1
outputTargetType: UnityEngine.AudioSource
sourceObject: Audio Track 1 (UnityEngine.Timeline.AudioTrack)


[binding]
streamName: Control Track 1
outputTargetType: 
sourceObject: Control Track 1 (UnityEngine.Timeline.ControlTrack)


[binding]
streamName: Signal Track
outputTargetType: UnityEngine.Timeline.SignalReceiver
sourceObject: Signal Track (UnityEngine.Timeline.SignalTrack)


[binding]
streamName: Playable Track
outputTargetType: 
sourceObject: Playable Track (UnityEngine.Timeline.PlayableTrack)


[binding]
streamName: PlayableBehaviour Logger
outputTargetType: 
sourceObject: PlayableBehaviour Logger (UnityEngine.Timeline.PlayableTrack)


[binding]
streamName: G1-Activation Track
outputTargetType: UnityEngine.GameObject
sourceObject: G1-Activation Track (UnityEngine.Timeline.ActivationTrack)


[binding]
streamName: G1-Animation Track
outputTargetType: UnityEngine.Animator
sourceObject: G1-Animation Track (UnityEngine.Timeline.AnimationTrack)


            */

PlayableDirector.playableAsset.GetOutputTracks()

型:TrackAsset

/*
            name オブジェクト名
            start
            end
            duration    インスタンス化されたPlayableの再生時間(秒単位)。
            muted トラックをミュートし、作成した PlayableGraph から除外します。
            mutedInHierarchy
            locked The local locked state of the track.
            lockedInHierarchy The locked state of a track. (Read Only)
            parent トラックの所有者。 TimelineAsset
            isEmpty このトラックにクリップが含まれているか。
            isSubTrack このトラックはサブトラックか。
            outputs インスタンス化した Playable の出力の説明。 PlayableBinding
            timelineAsset このトラックが属する TimelineAsset。
            GetChildTracks サブトラック、または、トラックに設定された子トラックのリスト。 Group配下のTrackなど
            GetClips トラックが所有するクリップのリストを返します。
            GetGroup    Group配下のTrackで自分のGroupTrackを取得できる
            GetMarkers  ヘッダーのMarkerTrack、SignalTrackで取得できる


[trackAsset]
name: Markers
start: 11.233333333333
end: 11.233333333333
duration: 0
muted: False
mutedInHierarchy: False
locked: False
lockedInHierarchy: False
parent: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
isSubTrack: False
outputs: Markers
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
GetMarkers: Signal Emitter/Signal Emitter/MySamples/Annotation1


[trackAsset]
name: Activation Track 1
start: 0
end: 6
duration: 6
muted: False
mutedInHierarchy: False
locked: False
lockedInHierarchy: False
parent: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
isSubTrack: False
outputs: Activation Track 1
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
GetClips: Active A/Active B/Active C
            
[trackAsset]
name: Animation Track 1
start: 2
end: 7
duration: 5
muted: False
mutedInHierarchy: False
locked: False
lockedInHierarchy: False
parent: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
isSubTrack: False
outputs: Animation Track 1
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
GetClips: angry


[trackAsset]
name: Audio Track 1
start: 0
end: 201.980666666667
duration: 201.980666666667
muted: False
mutedInHierarchy: False
locked: False
lockedInHierarchy: False
parent: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
isSubTrack: False
outputs: Audio Track 1
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
GetClips: MusMus-BGM-042/jump


[trackAsset]
name: Control Track 1
start: 14.464
end: 19.464
duration: 5
muted: False
mutedInHierarchy: False
locked: False
lockedInHierarchy: False
parent: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
isSubTrack: False
outputs: Control Track 1
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
GetClips: Child


[trackAsset]
name: Signal Track
start: 14.464
end: 14.464
duration: 0
muted: False
mutedInHierarchy: False
locked: False
lockedInHierarchy: False
parent: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
isSubTrack: False
outputs: Signal Track
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
GetMarkers: Signal Emitter


[trackAsset]
name: Playable Track
start: 19.464
end: 24.464
duration: 5
muted: False
mutedInHierarchy: False
locked: False
lockedInHierarchy: False
parent: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
isSubTrack: False
outputs: Playable Track
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
GetClips: ColorTransitionClip
            
[trackAsset]
name: PlayableBehaviour Logger
start: 2
end: 7
duration: 5
muted: True
mutedInHierarchy: True
locked: False
lockedInHierarchy: False
parent: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
isSubTrack: False
outputs: PlayableBehaviour Logger
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
GetClips: SimplePlayableAsset


[trackAsset]
name: G1-Activation Track
start: 0
end: 4
duration: 4
muted: False
mutedInHierarchy: False
locked: False
lockedInHierarchy: False
parent: Group1 (UnityEngine.Timeline.GroupTrack)
isSubTrack: False
outputs: G1-Activation Track
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
GetClips: Active/Active
GetGroup: Group1


[trackAsset]
name: G1-Animation Track
start: 0
end: 25.55
duration: 25.55
muted: False
mutedInHierarchy: False
locked: False
lockedInHierarchy: False
parent: Group1 (UnityEngine.Timeline.GroupTrack)
isSubTrack: False
outputs: G1-Animation Track
timelineAsset: ObjectRelationAnalyTimeline (UnityEngine.Timeline.TimelineAsset)
GetClips: Idle
GetGroup: Group1
             */

PlayableDirector.playableAsset.GetOutputTracks().GetClips()

型:TimelineClip

/*
                displayName
                start クリップの開始時刻。
                end クリップの終了時刻。
                duration クリップの長さ (秒)。
                asset シリアライズ可能な IPlayableAsset への参照で、クリップの特殊性を示します。 Clipを表すPlayableAsset
                animationClip アニメーション化したパラメーターを含む AnimationClip。
                clipCaps このクリップがサポートする主な機能。
                clipIn クリップの再生を開始する時刻。
                extrapolatedDuration 補外部分も含むクリップの長さ。
                extrapolatedStart 補外部分も含むクリップの開始時刻。
                hasBlendIn クリップにブレンドインがあるか。
                hasBlendOut クリップに、0 以外のブレンドアウトがあるか。
                hasPostExtrapolation クリップの終了時以降に補外があるか。
                hasPreExtrapolation クリップの開始時以前に補外があるか。
                parentTrack Returns the parent track where this clip is attached.
                postExtrapolationMode クリップの終了後のギャップに対する補外モード。
                preExtrapolationMode クリップの開始前のギャップに対する補外モード。
                timeScale クリップのタイムスケール。


[timelineClip]
displayName: Active A
start: 0
end: 2
duration: 2
asset: ActivationPlayableAsset (UnityEngine.Timeline.ActivationPlayableAsset)


[timelineClip]
displayName: Active B
start: 2
end: 4
duration: 2
asset: ActivationPlayableAsset(Clone) (UnityEngine.Timeline.ActivationPlayableAsset)


[timelineClip]
displayName: Active C
start: 4
end: 6
duration: 2
asset: ActivationPlayableAsset(Clone)(Clone) (UnityEngine.Timeline.ActivationPlayableAsset)


[timelineClip]
displayName: angry
start: 2
end: 7
duration: 5
asset: AnimationPlayableAsset (UnityEngine.Timeline.AnimationPlayableAsset)


[timelineClip]
displayName: MusMus-BGM-042
start: 0
end: 164.780408163265
duration: 164.780408163265
asset: AudioPlayableAsset (UnityEngine.Timeline.AudioPlayableAsset)


[timelineClip]
displayName: jump
start: 194.516666666667
end: 201.980666666667
duration: 7.464
asset: AudioPlayableAsset (UnityEngine.Timeline.AudioPlayableAsset)


[timelineClip]
displayName: Child
start: 14.464
end: 19.464
duration: 5
asset: ControlPlayableAsset (UnityEngine.Timeline.ControlPlayableAsset)


[timelineClip]
displayName: ColorTransitionClip
start: 19.464
end: 24.464
duration: 5
asset: ColorTransitionClip (MySamples.Experiment.ColorTransitionClip)


[timelineClip]
displayName: SimplePlayableAsset
start: 2
end: 7
duration: 5
asset: SimplePlayableAsset (MySamples.PlayableGraphs.SimplePlayableAsset)


[timelineClip]
displayName: Active
start: 0
end: 2
duration: 2
asset: ActivationPlayableAsset (UnityEngine.Timeline.ActivationPlayableAsset)


[timelineClip]
displayName: Active
start: 2
end: 4
duration: 2
asset: ActivationPlayableAsset(Clone) (UnityEngine.Timeline.ActivationPlayableAsset)


[timelineClip]
displayName: Idle
start: 0
end: 25.55
duration: 25.55
asset: AnimationPlayableAsset (UnityEngine.Timeline.AnimationPlayableAsset)
                 */

Clipの動き

エディタ再生時

Clipの振る舞いであるCustomeBehaviourにログを仕込んだ結果が次の通り。 先頭の数字は実行時のグローバルなFrame番号。

//479 create: logging
//479 start: logging
//479 pause: logging
//687 play: logging
//687 prepare: logging
//687 process: logging
//688 prepare: logging
//688 process: logging
//689 prepare: logging
//689 process: logging
//690 prepare: logging
//690 process: logging
//...
//830 prepare: logging
//830 process: logging
//831 prepare: logging
//831 process: logging
//832 prepare: logging
//832 process: logging
//833 prepare: logging
//833 process: logging
//834 prepare: logging
//834 process: logging
//835 pause: logging
//4117 stop: logging
//4117 destroy: logging

PlayableDirectorのPlayメソッドを実行したのが479Frameとなる。 Clipは、PlayableDirectorがPlayされる時に生成される。Clipの範囲に再生ヘッドがない場合はすぐにPause状態になる。 再生ヘッドがClipに入るとClipがPlayになり、抜けるとPauseに戻る。 PlayableDirectorでTimelineが終了するとstop、destroyとなる。

PlayableDirectorでは、Playする時にGraphが生成され終了するとGraphが破棄される。

エディタ停止中

TimelineエディタでTimelineを開いた時に、create、start、pauseが呼ばれる。 再生ヘッドがClipに入ると、play、prepare、processが呼ばれる。(Timeline停止してても) 抜けるとpauseになる。 Timelineを再生して終了まで行くと、stop、start、pauseを繰り返す。 Clipのサイズや位置を変更すると、stop、destroy、create、start、pauseが呼ばれ、Graphが逐次再生成されているのが分かる。