時代に翻弄されるエンジニアのブログ

ゲームプログラマをやっています。仕事やゲームや趣味に関してつらつら書きたいと思います。

TimelineAsset を Instantiate するときに気をつけること

f:id:tkymx83:20210307172908p:plain

こんにちは、たくという名前でブログやっております。

Unityには、Timelineという時系列に沿った処理をかんたんに記載できる機能があります。

ゲームでは演出などの一連の流れを作るために使ったりします。

今日はこのTimelineを使っていてある問題を解決したので共有します。

Timeline とは?

Timeline とは、Unity で時系列に沿った処理をかんたんに行う機能です。

時系列ごとに行う処理をTimelineAsset という アセットに記載して、ゲーム中に呼び出すことで演出を行う事ができます。

ただ、ゲームではインタラクティブに状態が変わるため、動かしたいオブジェクトが動的に変わることもあります。

そのため、TimelineAsset に記載された処理の対象をプログラム的に再指定する必要があります。

今回起きた問題

TimelineAsset に記載された処理の対象をプログラム的に再指定 を行ったところ、呼び出し元のファイルの参照も変更されてしまいました。

もともとは以下の画像のように参照のオブジェクトが設定されていました。(Object1, Object2 が参照先を表しています。)
f:id:tkymx83:20210307171032p:plain

ところがランタイムで処理対象の再設定を行ったところ、アセットの参照が以下のように None になってしまいました。つまり参照が外れてしましました。
f:id:tkymx83:20210307171157p:plain

原因は?

ゲーム中での動作自体が TimelineAsset のファイル自体の参照を変更してしまっていたからです。

対策は?

TimelineAsset を Object.Instantiate を使用して複製してしようすることです。複製することで参照を変えても、プログラム上で複製された方の参照が変わるため、元のアセットファイルの参照が変わるわけではないためです。

しかし注意点があります。

まず、TimelineAsset は以下のような構造を持っています。

  • TimelineAsset は TrackAssetの参照 を複数持っている
  • TrackAsset は TimelineClip を複数持っている
  • TrackAsset は親のTimelineAssetの参照を持っている
  • TimelineClip には PlayableAssetの参照 を一つ持っている

図とするなら以下のような形です
f:id:tkymx83:20210307171659p:plain

そのため、以下2点の対策が必要です。

①TimelineAsset, TrackAsset, PlayableAsset それぞれを複製する

TimelineAsset を Object.Instantiate を使用して複製しても、TrackAsset や PlayableAsset は もとのアセットに参照がされているので、TrackAsset の参照をプログラム上で変えたばあい、元のファイルの参照が変わってしまいます。

そのため、すべての TimelineAsset, TrackAsset, PlayableAsset の複製が必要になります。

②Instantiate 後に 元のアセットのTrackAsset の親への参照を 元のアセットのTimelineAsset に変更する


TimelineAsset を Object.Instantiate を使用して複製 した場合、子の TrackAsset が持っている 親の TimelineAsset の参照が複製された TimelineAsset に変更されます。

そのため、ゲームを終了した際に、複製された TimelineAsset は消えてしまうため、親がいないという状態になり、コンソールでエラーが表示されます。

よって、Instantiate 後に 元のアセットのTrackAsset の親への参照を 元のアセットのTimelineAsset に変更する 必要があります。

注意点

上記で解説した2つの方法は、通常アクセスできるメソットやフィールドが用意されていません。そのため、リフレクションなどを利用して、隠蔽されたメソッドを利用する必要があります。

*もし何か他にいい方法があれば教えて下さい。

TimelineAssetの複製部分のコードを公開下の参考にしてください

gist.github.com