[Unity] TimelineのPlayableTrackで遊ぼう 1
2017から追加されたTimelineが便利そうにみえたので、
実験がてらいろいろと動作を試してみました。
Timelineは、その名の通りタイムライン上にいろいろなアセットやアニメーションを配置することができるもので、演出なんかを作るのに使えそうな機能になります。
AssetsにTimelineを作成し、オブジェクトに対してPlayableDirectorをアタッチすることで使用することができます。
基本は、ムービーの再生などと同じで.Play することで、タイムライン上に並べたアセットやアニメーションを、時間軸にそって再生してくれます。
デフォルトで使えるのが、
アセットのShowHideを行えるActivation
アセットの読み込みができるControlTrack
アニメーションの再生ができるAnimationTrack
オーディオを再生することができるAudioTrack
スクリプトを実行できるPlayableTrack等があります。
その他に別途アセットを導入することで、Movie再生(ただし連続再生はできない)や
フェード、2オブジェクト間のスイッチなどを行うことが出来るようになります。
その中でも、若干最初イミフだったスクリプトをアタッチできるPlayableTrackについてのメモ。
PlayableTrackを使用したい場合は、CreateからPlayablesのPlayableBehaviour・PlayableAssets
から、C#スクリプトを作成します。
Unityのタイムラインの構造は、大きく分けて
Track > Assets > Clip(Behaviour)
のような入れ子構造になっていて
Trackが1つの操作単位で、Actiovation、Control、Animationのように「なにを」操作するのかで
それ1つがタイムラインを持っています。
その中にAssetsがあり、自分でもこの辺の理解は怪しいですが、
PlayablesAssetsがUnity本体との間を取り持つプラグのような扱いで、そこから受け取った情報を
どのタイミングで実行するのか というのを Clip(Behaviour)で制御している認識です。
まずは、PlayableAssetを作成してシーン上のオブジェクトを受け取れるようにします。
今回は、こんな感じでフェードアウトするスクリプトをタイムラインから操作してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FadeOut : MonoBehaviour { private Material mat; public float fadeTime = 1.0f; private float deltaTime = 0f; // Use this for initialization void Start () { mat = GetComponent<Renderer>().material; StartCoroutine("fadeout"); } IEnumerator fadeout(){ while(deltaTime < fadeTime){ deltaTime += Time.deltaTime; mat.SetFloat("_Opacity",Mathf.Lerp(1,0,deltaTime / fadeTime)); yield return null; } mat.SetFloat("_Opacity",0); } } |
フェードアウトするスクリプトはこんな感じ。
シェーダーはShaderForgeでOpacityだけついたものをテストで作成しました。
とりあえずTimelineを作成し、PlayableTrackを追加。
その後、右クリックでAddClipで作成したAssetsを選択します。
配置できました。
これだけだとなにもおこらないので、AssetsとBehaviourを編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; [System.Serializable] public class TestPlayableAssets : PlayableAsset { public ExposedReference<FadeOut> fade; // Factory method that generates a playable based on this asset public override Playable CreatePlayable(PlayableGraph graph, GameObject go) { TestPlayableBehaviour b = new TestPlayableBehaviour(); b.fade = fade.Resolve (graph.GetResolver()); return ScriptPlayable<TestPlayableBehaviour>.Create (graph, b); } } |
TimeLineからシーン内にオブジェクトを参照するには、通常のやり方だとNGなので
ExposedReferenceというクラスを経由します。
exposedは「晒す」の意味で、意味合いとしてはセットしたオブジェクトへの参照を作成する…的な機能を持つようです。
この辺はもう正直「お約束」的なおぼえ方しかしていません(汗
とりあえず、上のようにすると、実際の処理をかくBehaviourにシーンのオブジェクトを渡すことが出来ます。
つづいてBehaviour
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; // A behaviour that is attached to a playable public class TestPlayableBehaviour : PlayableBehaviour { public FadeOut fade; // Called when the owning graph starts playing public override void OnGraphStart(Playable playable) { fade.fadeTime = (float)playable.GetDuration(); } // Called when the state of the playable is set to Play public override void OnBehaviourPlay(Playable playable, FrameData info) { fade.startFade(); } } |
タイムラインで実行するタイミングごとに関数をオーバーライドします。
OnGraphは、Traskの開始時 OnBehaviourPlayは、Clipが始まったタイミングで呼ばれます。
今回は、Clipの長さでフェードアウトしてほしかったので
まず、起動時にClipの長さを取得してFadeを制御しているオブジェクトに渡します。
そして、実際にClipが再生はじめたらフェードを開始するようにしています。
結果がこんな感じ。
最初は、1つのやりたい事に対してスクリプト2つ???で面食らいましたが
基本の押さえるところさえ押さえればわりと色々出来そうだというのが分かりました。
注意点
PlayableBehaviourで1つ引っかかったのが、Clip終了時に実行される OnBehaviourPause が、
Track開始時に実行されてしまうところ。
当初、Clip終わったらXXXの処理をする…のようなものをつくってみたのに
何故か変なところで実行が始まる…という現象に襲われて、気づくまで時間がかかってしまいました。
(仕方ないので 1回目は実行しない みたいなboolのフラグをつくって回避)
どうしてこうなった…
あと、便利そうにみえるTimelineですが
最近追加された機能のおかげでバージョンアップごとに挙動が異なってたり色々変更されてたりするようなので、がっつり使うにはやや怖い印象があります。
正直テストしていても、未開拓感ば半端なく 便利なのかそうじゃないのか判断しかねることが多かったです。
とはいえ、映像制作的な使い方をするならとても便利な機能ですし
PlayableAssetsも慣れてしまえば、指定のタイミングでXXXするみたいなことも
簡単に作れるし調整もしやすいので、こなれてきたらもっと便利になるんじゃないかなーと思うので
引き続き色々と検証してみようと思います。
参考