
AssetBundle設計のとある形
前回、AssetBundleを利用する際に考慮すべきことを記事にしましたが、その実例を紹介したいと思います。全体的に何を考慮すべきなのかを知りたい人は、前の記事「AssetBundle設計コトハジメ」を見てください。
●1つのAssetBundleに含めるAssetの数やルール
基本的には1Asset = 1AssetBundle。
ただし、同時利用することが確定しているAssetは、複数まとめてAssetBundle化します。
また、
こんなイメージでAssetをロードする側が、非同期でAssetのロードを待ち、そのAssetがアプリ内(Resources/)からロードされるのか、ダウンロードが必要なのかは基本的に意識しないつくりにしています。
そのため、Resources以下に配置するAssetのパスとAssetBundleのパスは同一にする、というルールにしています。
例:
「hoge/hogehoge.png」の場合、以下のようになります。
Assetをロードする場合に指定するパス :hoge/hogehoge
アプリ内に配置する場合のAssetのパス :Resources/hoge/hogehoge.png
ダウンロードする場合のAssetBundleのパス:https/xxx/hoge/hogehoge.assetbundle
複数Assetを1つのAssetBundleにする場合は、ディレクトリ名をAssetBundle名にします。
例:
「chara01/hoge.pngとchara01/fuga.png」を一つのAssetBundleに含める場合、以下のようになります。
Assetをロードする場合に指定するパス:chara01/hoge, chara01/fuga
アプリ内に配置する場合のAssetのパス :Resources/chara01/hoge.png, Resources/chara01/fuga.png
ダウンロードする場合のAssetBundleのパス:https/xxx/chara01.assetbundle
このように、パスやリソースのロードを工夫することで、アプリ内(Resources/)に配置するAssetとダウンロードするAsset(別ディレクトリ)を簡単に入れ替えられるようにしています。
また、この構成から察するかもしれませんが、ダウンロードするタイミングは、Assetが必要になった(ロード要求をした)タイミングになります。アプリ起動時など、特定のタイミングでダウンロードを済ませて起きたい場合は、予めダウンロードするAssetのリストを作っておき、そのタイミングでまとめてロードする、といった使い方も可能です。
●Unloadするタイミング
前述のとおり、今回はAssetBundleに含まれるAssetはすべて同時利用されるのと、Unity5.3から登場したLZ4形式なら必要な分だけしかメモリを消費しないため、Assetをロード後にすぐUnloadするのではなく、Assetへの参照がなくなった時点でUnloadするようにしています。
●ロード方法と圧縮形式
現状はキャッシュ(WWW.LoadFromCacheOrDownload、UnityWebRequest.GetAssetBundle)を利用しているため、
「LZMA(ダウンロード時) → LZ4(端末に保存、ロード時)」
となります。
今のところダウンロードするリソースの量はそれほど多くない予定ですが、バージョン管理の仕組みなどは用意したため、後でAssetBundle.LoadFromFileを使った実装に変える、というのも比較的容易にできるようにつくったつもりです。
●AssetBundleビルドの工夫
基本的には1Asset = 1AssetBundleのため、指定したディレクトリ以下にあるAssetはAssetBundle名を自動で設定しています。
ディレクトリ単位でAssetBundleにしたい場合は、エディタ拡張のメニューで設定を変更します。
※GroupFlg Onにするとディレクトリ名のAssetBundleに対象Assetが含まれるようになります
※特定のルールが決まったディレクトリはAssetImporterで自動設定しています
EditorWindowを利用して、AssetImporterのassetBundleName、assetBundleVariant、userDataあたりを設定しています。
参考:
https://docs.unity3d.com/ja/current/ScriptReference/EditorWindow.html
https://docs.unity3d.com/jp/current/ScriptReference/AssetImporter.html
AssetBundle名の命名規則とこの対応で、手入力によるAssetBundle名の設定は撲滅しています。
AssetBundleビルドからアプリにダウンロードされるまでのフローは以下のようになります。
①Assetbundleビルド(図左上)
専用マシンを用意して、AssetBundleの対象ファイルを追加したり変更する際は、そのマシンで行うようにしています。こうすることで、UnityのAssetBundleビルドが差分だけ走るようにしています。(git経由で別マシンからプッシュしたAssetは再度AssetBundleビルドが走ってしまったり、ファイルの更新日時も変わってしまって管理しづらいため)
ビルド時に、更新されたAssetBundleの更新日時を元に、AssetBundle毎のバージョンを上げていきます。
②アップロード(図左下)
AssetBundleビルド後に更新があったAssetBundleはワンクリックでサーバへアップできるようにしています。この際に、AssetBundleのバージョン情報をcsvファイルに吐き出して、git経由でAPIサーバが参照するDBに登録します。アプリからはこのバージョンを参照してダウンロード判定を行います。
③端末からのAPI通信時(図右下)
アプリからサーバに通信を行う際に、AssetBundle(リソース)のバージョンチェックを行います。新しいバージョンが登録されている場合、そのリストを取得します。
④リソース(Asset)ロード時(図右上)
Assetをロードする際に、③で取得したバージョンをチェックし、未ダウンロードの場合や新しいAssetBundleがサーバ上にある場合、ダウンロードした後にAssetをロードします。ダウンロード対象のAssetじゃない場合はアプリ内(Resources)からロードします。
●依存関係とAssetBundleManifest
AssetBundleビルド時にできるAssetBundleManifestから、独自の管理ファイルを作成しています。
用途としては、AssetBundleManifestと同じく依存関係の管理と、バージョン管理、AssetとAssetBundleの紐付けを確認するためのものです。
●まとめ
実現したもの
・アプリ内に配置するAssetとダウンロードするAssetの入れ替えを容易に
・AssetBundle名の自動設定
・AssetBundleビルドした後のリソースをワンクリックでサーバへアップロード
・AssetBundleの依存関係を動的に解決
・バージョン管理の仕組み
残っている課題
・不要になったAssetBundleを削除する仕組み
・同時ダウンロード数の制御
となります。
この記事へのコメントはありません。