【Unity Timeline メモ】 Activation Trackを使用したスクリプト実行での注意点

# はじめに
Unity TimelineのActivation Trackで適当なオブジェクトを割り当て、そのオブジェクトの`OnEnable()`,`OnDisble()`でスクリプトを実行する方法があります。
その方法を試そうとActivation Trackをいじくりまわしていたところ、`OnEnable()`が何故かTimeline上で非アクティブにしているのにも関わらず、最初に実行されたり、また弄ると実行されなかったりと、動作がよくわからなかったので、実行結果が変化する原因を探ってみました。

結果だけ知りたい方は、[現状でわかったこと](https://qiita.com/nyu___nS/items/d65177e1ce3b13fab7bf#%E7%8F%BE%E7%8A%B6%E3%81%A7%E3%82%8F%E3%81%8B%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8) まで読み飛ばしてください。

#環境
* Unity2018.1.3f1

# Activation Trackで関わってくる知識
## Unityのイベント関数について
Unityのイベント関数について、詳しくは [イベント関数の実行順](https://docs.unity3d.com/ja/current/Manual/ExecutionOrder.html)を見てください。

``` Start()```, ```Update()```,```OnEnable()```,```OnDisable()```については、以下の通りになります。

### Start()
>スクリプトのインスタンスが有効になると、最初のフレームのアップデート前に Start が呼び出される

Update()の前に呼び出される関数です。

### Update()
>フレームごとに一度呼び出されます。これは、フレームのアップデートのメインとなる関数です。

### OnEnable()
> (オブジェクトがアクティブな場合にのみ呼び出されます。) この関数は、オブジェクトを有効にした直後に呼び出されます。これは、MonoBehaviour インスタンスが作成されたとき (例えば、レベルが起動されたときや、スクリプトコンポーネントがアタッチされたゲームオブジェクトがインスタンス化されたとき) に発生します。

[Unityでタイムラインを使ってゲームのイベントシーンの動きを作成してみる](https://gametukurikata.com/basic/timeline)
では、タイムライン上でシーンの切り替えを行う際に```OnEnable()```を使用していました。
今回、私もこの記事を参考にし、あるタイミングでタイムラインを切り替えるためにこの関数を使用しました。

### OnDisable()
>オブジェクトが破棄される直前のフレーム更新後に OnDestroy が呼び出されます。(オブジェクトは Object.Destroy あるいはシーン終了時に破棄されます)

### 実行順番
実行順番は

1. ```OnEnable()```
* ```Start()```
* ```Update()```
* ```OnDisable()```

になります。

## Playable Directorについて
Playable Directorのプロパティーについて、`Play On Awake`と`Wrap Mode`について説明します

![](https://i.gyazo.com/770cd6b1800d0798fce501d975e2c9a6.png)
### Play On Awake
チェックすることでゲームプレイ開始と同時にタイムラインも動作します。

### Wrap Mode
タイムラインインスタンスが再生を終了するときの動作です
 
* __Hold__
 * タイムラインの最後の状態を維持します。
* __Loop__
 * タイムラインを繰り返し再生します。
* __None__
 * タイムラインの再生前に戻します。

## ロックボタン
Timelineの右上にあるボタン
![image.png](https://qiita-image-store.s3.amazonaws.com/0/92777/46cca050-6d47-f28a-6eea-f77f0938c90a.png)
他のオブジェクトを押したとき、勝手にTimeline参照先が切り替わらないようにするもの。
とりあえず、ここを押しとけといわれる箇所。
正直よくわかっていません:rolling_eyes:

[Unity2017のTimelineをやってみた](https://blog.applibot.co.jp/2017/06/16/unity2017timeline/)　によると
>Timelineウィンドウは、他のオブジェクトを選択するたびに表示が途切れますので、ロックをかけておくことをおすすめします。
また、「Preview」が押されていない場合は、Trackにオブジェクトを紐付けることができません。Previewが押せない場合は、
一度noneを選択して、再度指定のTimelineを選ぶと押せるようになります。

と書いてました
## Previewボタン
Timelineの左上にあるボタン
![image.png](https://qiita-image-store.s3.amazonaws.com/0/92777/a70e47bf-eed4-64fc-bb75-368606b1a4ab.png)
よくわかってません:rolling_eyes:

# 用意したもの
Cubeオブジェクトを用意し、そこに作成したスクリプトをアタッチします。
![](https://i.gyazo.com/8a1fa650a76213404d992d4971a12272.png)

作成したスクリプトは以下になります。

```cs:EventTest.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EventTest : MonoBehaviour {

	// Use this for initialization
	private bool isOnceUpdate=true;
	void Start () {
		Debug.Log("Start");
	}
	
	void OnEnable(){
		Debug.Log("OnEnable");
	}
	// Update is called once per frame
	void Update () {
		if(!isOnceUpdate) return;

		Debug.Log("Update");
		isOnceUpdate=false;
	}

	void OnDisable(){
		isOnceUpdate=true;
		Debug.Log("OnDisable");
	}
}
```

`Update`が何回も表示されるのは鬱陶しいので、１回だけ表示するようにしました。
また、タイムラインも２つ用意しました。

* Activeタイムクリップを再生直後に配置したTimeLine（__FirstActive__）
 * ![](https://i.gyazo.com/c05613b643b6998aeed02550223f15d0.png)
 * emptyはTimelineの再生長さを長くするために配置しています。
* Activeタイムクリップを再生から少し時間をおいて配置したTimeLine（__LastActive__）
 * ![](https://gyazo.com/7f3b9f09bc1582752945c18ab28a29a0.png)

# 現状でわかったこと
いろいろと弄っていた結果、
__Previewボタン__を__OFF状態__で、スクリプトをアタッチしているオブジェクトをアクティブにすれば、実行時にそのオブジェクトがアクティブになり（おそらくフレーム１回分）、その後、TimelineのActivation Trackにそってアクティブ状態が切り替わることがわかりました

わかりにくいので、具体例を出します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/92777/3c914501-7451-4c71-5721-1401d7c0a243.png)
ここでは、Activeタイムクリップを再生から少し時間をおいて配置したTimeLine(LastActive)を用意し、EventTestというオブジェクトをバインディングしてます。また、EventTestにはEventTest.csを割り当てています。
現在、__Preview : ON__でEventTestが__非アクティブ__になっていますが、
__Preview : OFF__にすると
![image.png](https://qiita-image-store.s3.amazonaws.com/0/92777/5458b90d-70bf-4892-4249-d3e75b728be0.png)
EventTestが__アクティブ__になります。
TimeLineを非アクティブにした場合もEventTestが__アクティブ__になります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/92777/9510110a-a972-c701-07f3-0b61b5f23c9f.png)

つまり、EventTargetはTimelineに操作されていない状態ではアクティブ状態にあるので、
実行した場合、最初に`OnEnable()`や`Start()`が呼ばれます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/92777/1946e8c6-f90e-f846-094e-58f31b255c63.png)
実行回数は１回ずつ実行していました。

なぜそのようなことになるかは具体的には調べ上げていないのですが、
Activation Trackを使ったスクリプト実行をしようとして上手くいかなければ
__Previewボタン__を疑ってください。

# 最後に
おそらく、[【Unity】知らないと苦労するかもしれない、Timelineと座標の話](http://tsubakit1.hateblo.jp/entry/2018/05/15/004014)の「Timelineを編集後、キャラの位置がズレるのはPreview中にキャラの位置を編集しているため」の項目に書かれている内容と似ている気がします。

どなたか詳しい方がいらっしゃいましたら、教えていただきたいです。

# 参考文献
* [【Unity】コンポーネントのイベント実行順についてのTips](http://tsubakit1.hateblo.jp/entry/2017/02/05/003714)
* [Unityでタイムラインを使ってゲームのイベントシーンの動きを作成してみる](https://gametukurikata.com/basic/timeline)
* [Unity2017のTimelineをやってみた](https://blog.applibot.co.jp/2017/06/16/unity2017timeline/)
* [【Unity】知らないと苦労するかもしれない、Timelineと座標の話](http://tsubakit1.hateblo.jp/entry/2018/05/15/004014)