Unity Timelineで待ち受け処理っぽい事を実装する

初期化処理の完了待ちを行ったり、途中のロード完了を待ち受けたい時に
タイムラインでどうやって実装したら良いかわからなかったので調査してみました。

参考URL：
https://blogs.unity3d.com/jp/2018/04/05/creative-scripting-for-timeline/
https://github.com/UnityTechnologies/ATerribleKingdom

■前提
テスト用にUpdate文の中で数字を加算するだけの簡単な処理を作りました。
数値が1000を超えるとFLGがTrueになり、Trueになるとタイムライン側のループをやめて
次のクリップの処理に移行するようにしました。
（Update文内の処理はかなり雑）

■処理
数値が1000を超えるまではCubeが表示され、それ以降はSphereが表示されるという簡単なものです。

■Playble Assetが参照しているオブジェクトにあたっちされているソース

```FlgChange.cs
using UnityEngine;

public class FlgChange : MonoBehaviour
{
    public bool IsEnd = false;
    int count = 0;
    // Start is called before the first frame update
    void Start()
    {
        IsEnd = false;
        count = 0;

    }

    // Update is called once per frame
    void Update()
    {
        count++;
        Debug.Log("count=" + count);
        if(count > 1000)
        {
            Debug.Log("IsEnd=" + IsEnd);
            IsEnd = true;
        }
    }
}
```


■Playble Asset

```TestWaitAsset.cs
using UnityEngine;
using UnityEngine.Playables;

[System.Serializable]
public class TestWaitAsset : PlayableAsset
{
    public ExposedReference<FlgChange> FlgChangeValue;

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

        testBehaviour.TestFlgChange = FlgChangeValue.Resolve(graph.GetResolver());

        return testPlayable;
    }
}

```

下記の**時間を巻き戻す処理**でタイムラインの初めまで戻します、
数値指定すればそこに戻るはず。

おそらくフレーム単位の形でも時間単位の形でも戻すことも可能なはず（調べてません。）

```
// 時間を巻き戻す
(playable.GetGraph().GetResolver() as PlayableDirector).time = 0.00d;
```


■Playable Behaviour

```TestWaitBehaviour.cs
using UnityEngine;
using UnityEngine.Playables;

// A behaviour that is attached to a playable
public class TestWaitBehaviour : PlayableBehaviour
{
    public FlgChange TestFlgChange;

    private bool clipStart = false;

    // Called when the owning graph starts playing
    public override void OnGraphStart(Playable playable)
    {
        clipStart = false;
    }

    // Called when the owning graph stops playing
    public override void OnGraphStop(Playable playable)
    {
        
    }

    // Called when the state of the playable is set to Play
    public override void OnBehaviourPlay(Playable playable, FrameData info)
    {
        clipStart = true;
    }

    // Called when the state of the playable is set to Paused
    public override void OnBehaviourPause(Playable playable, FrameData info)
    {
        if(playable.IsNull())
        {
            return;
        }
        Debug.LogError("IsEndLoop=" + TestFlgChange.IsEnd);
        Debug.LogError("clipStart=" + clipStart);
        if(clipStart)
        {
            if(!TestFlgChange.IsEnd)
            {
                // 時間を巻き戻す
                (playable.GetGraph().GetResolver() as PlayableDirector).time = 0.00d;
            }
        }
    }

    // Called each frame while the state is set to Play
    public override void PrepareFrame(Playable playable, FrameData info)
    {
    }
}

```

■タイムラインの設定（Playable Assetのセットされている区間を繰り返す）
![Timelineビューの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17904/ab44cc46-7b85-1543-16b7-80a4c22ab2c4.png)

■PlayableAssetの設定
![PlayableAssetの設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17904/2d85b295-1e2b-b9f0-a3bb-cc8411949bdb.png)