1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Unity】AssetBundleから生成したTimelineのトラックにオブジェクトを設定したい

1
Posted at

【背景】

Unityで制作しているゲームで、リソースをAssetBundleダウンロードで都度読み込む仕組みで制作を進めています。

キャラクターのSpriteなどをIDを指定して動的に取得するということはできましたが、
イベントシーンもAssetBundleで読み込んでうまく動かせるのか?ということを試しました。

元々はTimeline配下に動かすオブジェクトプレハブを配置していたのですが、
AssetBundleからダウンロードしてインスタンス化してみると、
バインドが消えていたりSpriteの参照が外れていたりと思うように動いてくれませんでした。

動かすオブジェクトの方は別のAssetBundleに入っているSpriteを参照していたせいだと思い、
AssetBundleは別々でUnity上で組み立てるという方法にしました。
依存関係も一緒にまとめてくれるはずなのですが…、
AssetBundle内のアセット一覧を見るとSpriteが入っていないようでした。

最終的に苦肉の策という形になりましたが、実現できた方法を残します。

【実現した方法】

概要としては、以下の処理順で実現できました。

1.Timelineで使用するオブジェクトを先にシーン上にインスタンス化

2.GameObject.Findで探してきて、PlayableDirector#SetGenericBinding

3.PlayableDirector#Playで再生

【前提】

Timelineである程度のルールが守られていることが前提になる方法です。

  • トラック名が使用するインスタンス名と一致している
    image.png

  • シーン上に先にGameObjectが生成されている

  • シーン上に同じ名前のGameObjectが存在しない

  • Timeline自体の配下にバインド対象を置かない
    ※Canvasはセリフなどを表示するためのテキストUIです
    image.png

1. Timelineで使用するオブジェクトを先にシーン上にインスタンス化

1.Timelineで動かすオブジェクトは、おおよそキャラクターSpriteだったり、カメラだったりになる想定です。

キャラクターのオブジェクトはSpriteをシーン上に配置してプレハブ化しています。
これは別途AssetBundleを作成しています。一応、AssetBundleは一度ダウンロードしたら静的なリストに入れておいて、ダウンロード済み確認をして重複を避けるという方法を考えています。

別途必要なAssetBundleを何らかの方法でTimelineに必要なAssetBundleリストを取得し、
Timelineのインスタンス化の前にシーン上に生成します。

自分の場合、アセットバンドルファイルの情報をDBの保持しており、WebAPIでキャラクターIDやイベントIDに紐づくファイル名を取ってくるようにしています。
AssetBundleファイルIDもキーにしているので、イベントIDとAssetBundleファイルIDで紐づけ構成可能かもしれません。

image.png

2.GameObject.Findで探してきて、PlayableDirector#SetGenericBinding

TimelineをAssetBundleから取得した後、インスタンス化する前にバインド処理を行います。

やっていることは単純で、Timelineの持つトラック名と一致するオブジェクトをシーン上から取得して、取得できていればSetGenericBindingしています。

Animation Trackとセリフ回し用のPlayabelAssetしか入っていないTimelineなので、ここではAnimation Trackのみ動的バインドしています。

// Assetのロード
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(uwr);
var assetPrefab = bundle.LoadAssetAsync<GameObject>("EventTimeline");

yield return assetPrefab;
GameObject prefab = (GameObject)assetPrefab.asset;

 PlayableDirector playableDirector = prefab.GetComponent<PlayableDirector>();

//playableDirector内のトラック(バインド先)を取得
foreach(var bindingTarget in playableDirector.playableAsset.outputs){
    //トラック名称の一致するオブジェクトをシーンから取得してバインド
    var bindObjectName = GameObject.Find(bindingTarget.streamName);
    if (bindObjectName) {
         playableDirector.SetGenericBinding(bindingTarget.sourceObject, bindObjectName.GetComponent<Animator>());
     }
  }

3.PlayableDirector#Playで再生

バインドループを抜けたらインスタンス化するかPlayでいざ再生

  GameObject instanse = Instantiate((GameObject)assetPrefab.asset);
  //または、playableDirector.Play();

カメラもオブジェクトも、うまくバインドできて動いてくれました。
今度はセリフ用のUIも別AssetBundleにするかシーン内の共通UIとして
動的にPlayableAssetのクリップにバインドできるとよいかもしれません。

Spriteの依存関係や動的なTimelineのバインド方法についてはもう少し
正当な方法を探してみようと思います。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?