Unity5 AssetBundle まとめメモ
今更ながら勉強した内容を忘れないためのメモ
Unity4から大幅に変更された
Unity4時代のAssetBundleは互換性がない()
Unity5.3からさらに変わったみたい
テラシュールブログ【Unity】Unity 5.3からAssetBundleはどう変わるのか…まとめ
タイプツリーが存在すればエディタのバージョンがあがっても互換は可能
AssetBundleのビルド
ビルドの前準備
アセットバンドルの名前にはいくつかの制限がある
- 小文字のみ
- path形式
Prefabs/Chara.unity3d(.unity3dが必要かどうか不明:バリアントがつくと拡張子がバリアントになる) - 同名禁止
- フォルダに名前を与えると直下にあるサブも含めたすべてがアセットバンドル化する
- 未使用なのにAssetBundle名がリストに登録してある
対象のアセットのインスペクター下にあるAsset Labels
という部分にそれぞれ
アセットバンドル名とバリアント名を記入できるメニューがある
左のポップアップメニューボタンがアセットバンドル名で、押してポップアップされるメニューからnew
メニュー
を選択してそこにpath形式でAssets/AssetBundle.unity3d
という風に書き込む
ビルドを実行すると、指定した出力先でAssetsフォルダが生成されその中に生成される
ビルドスクリプト
未だにUnity側でAssetBundleを生成してくれる機能はないので、自前で用意する必要があります
使用するメソッドは
BuildPipeline.BuildAssetBundles(
string outputPath,
BuildAssetBundleOptions assetbundleOptions = BuildAssetbundleOptions.None,
BuildTarget targetPlatform = BuildTarget.WebPlayer);
型 | 変数名 | 概要 |
---|---|---|
string | outputPath | 生成したアセットバンドルの出力先 |
BuildassetbundleOptions | assetbundleOptions | ビルドオプション |
BuildTarget | targetPlatform | 対象のプラットフォーム |
インスペクタでのアセットバンドル名設定によるビルドスクリプト
ビルド前準備で指定したアセットバンドル名
アセットバンドルをビルドするときは以下のようなエディタスクリプトを組み、実行するだけで良い
プロジェクトビューに適当にEditorフォルダを作り、ビルド用スクリプトを用意する
[MenuItem("AssetBundles/Build")]
static void BuildAssetBundles()
{
string outputPath = @"";
BuildAssetBundleOptions options = BuildAssetBundleOptions.None; // 特になし
BuildTarget target = EditorUserBuildSettings.activeBuildTarget; // 現在のビルドターゲットを取得
BuildPipeline.BuildAssetBundles(, BuildAssetBundleOptions options, BuildTarget target);
}
ビルドマップ方式のビルドスクリプト
AssetBundleBuildを利用した方法
AssetBUndleBuildの配列を用意し、それぞれの要素ごとのassetBundleName
にアセットバンドル名を指定
assetNames
という文字列配列にbundle化するアセットのパス"Assets/"から始まるパス名(拡張子付き)で指定する
// AssetBundle一つを作成する場合
AssetBundleBuild[] buildMap = new AssetBundleBUild[1];
buildMap[0].assetBundleName = "assetbundle.unity3d"
buildMap[0].assetBundleVariant = "hd"; // バリアントをつける場合は入れる
// 含めるアセットが一つの場合
buildMap[0].assetNames = new string[1]{"Assets/Resoruces/asset.prefab"};
BuildPipeline.BuildAssetBundles(@"AssetBundle/Android", buildMap, 0, BuildTarget.Android);
BuildAssetBundleOptions
これらの設定をBUildPipeline.BuildAssetbundles
に指定する
Noneに指定しても、依存関係を有効化するCollectDependencies
とオブジェクトのハッシュIDを使用するDeterministicAssetBundle
が有効になっている
- IngoreTypeTreeChanges
タイプツリーが変更されても無視 = ソースが変更されても変化したとは見なされない - DisableWriteTypeTree
タイプツリー自体を削除 - ForceRebuildAssetBundle
強制的にリビルド。変更が認められない場合はビルドしないのをさけるため - AppendHashToAssetBundleName
ハッシュを追加する。生成されるファイルの名前の下にハッシュが追加され、マニフェストにも記載される
AssetBundle Manifest
アセットバンドルに関する情報が書き込まれたテキストファイル。全体用と個別用が存在する
- シングルマニフェスト
全体管理のマニフェスト。依存関係等が乗る。実行時に読み込んで使用する。- すべてのAssetBundle名
- アセットの依存関係
- 個別マニフェスト
対応する名前のアセットバンドルのマニフェスト。インクリメンタルビルドにだけ関係する。実行時には読み込まない- CRC
- アセット名
- 依存関係
- Hash
- ClassTypes
インクリメンタルビルドは、BuildPipeline.BuildAssetbundles()
での出力先に
既に同名の.manifestファイルがあった場合に前回との差を比較してビルドを行うかどうかを判定する
Variant
HDとSDを同じアセットとして扱える仕組み
アセットバンドル名を登録するボタンの隣にある小さなボタンで設定を行う
小文字のみで指定するとファイル名の最後に拡張子がつけられる
AssetBundleのダウンロード
サーバ・StreamingAssetsフォルダなどに置かれたアセットバンドルをゲームにロードする
StreamingAssetsの場合
出力したファイルをプロジェクトのStreamingAssetsフォルダ以下に
ビルド時にbool BuildPipeline.GetCRCForAssetBundle(string targetPath, out uint crc);
を使用し
各々のAssetBundleのCRCを取得しておく
targetPathには出力されたアセットバンドルへのパスを拡張子まで入れる。out修飾子にCRCが帰ってくる。戻り値は成否
WWW.LoadFromCacheOrDownload
バージョン
WwW www = WWW.LoadFormCacheOrDownload(string url, int version, uint crc = 0);
ハッシュ版
WwW www = WWW.LoadFormCacheOrDownload(string url, Hash128 hash, uint crc = 0);
バージョン版では、Unity4から続くキャッシュ解放問題は解消されていない(Unity5.2の時点)
シングルマニフェストのロード
Manifestファイルに関してはWWW(string URL)
こちらを使用する
webPlayerやEditor実行などでStreamingAssetsフォルダを使用する場合は"File://"
などに注意する
AssetBundleのみをダウンロードすれば良いという場合は必須ではない
string URL = @"";
WWW download = new WWW(URL);
yield return download;
AssetBundleRequest request = null;
AssetBundleManifest manifest = null;
request = download.assetBundle.LoadAssetAsync("AssetBundleManifest", typeof(AssetBundleManifest));
yield return request; // ロードする
manifest = request.asset as AssetBundleManifest;
Manifestクラスの主な用途
// すべてのアセットバンドル名を取得する
string[] allAssetNames = manifest.GetAllAssetBundles();
// バリアントを持ったアセットバンドル名をすべて取得する
string[] variants = manifest.GetAllAssetBundlesWithVariant();
// 指定したアセットバンドルのハッシュを取得する
Hash128 hash = manifest.GetAssetBundleHash(string assetBundleName);
// 依存関係を持ったアセットバンドル名をすべて取得する
string[] dependencies = manifest.GetAllDependencies(string assetBundleName);
AssetBundleRequest
AssetBundleManifest
WWW.LoadFromCacheOrDownload(string url);
アセットバンドルの利用
assetbundle.LoadAsset();
NGUIのAtlasなど同名のオブジェクトが複数ある場合は拡張子(.prefab)まで指定しないとロードできない
Demo
アセットが必要になったタイミングで要求を行い、そこでダウンロードが行われる
AssetBundleManager.cs
ロードが完了したアセットバンドルを管理する、アセットバンドル名をキーとした辞書
ロードを管理したWWWをUpdateで監視し、Errorがあったらm_DownloadingErrorsにキーをアセットバンドル名、valueにエラー内容を書き込む
ダウンロードが完了すれば、Disposeし辞書から削除するそして
static Dictionary<string, LoadedAssetBundle> m_LoadedAssetBundles;
static Dictionary<string, WWW> m_DonwloadingWWWs;
static Dictionary<string, string> m_DownloadingErrors;
static List<AssetBundleLoadOperation> m_InProgressOperations;
キャッシュの個別クリア
CRCを利用した方法
WWW.LoadFromCacheOrDownload()
時に第三引数に当該のCRCを渡す。
このとき、Version値を固定にしているとCRC値が違えばキャッシュを削除してダウンロードし直す
通常のAB用のとは別のWWW.LoadFromCacheOrDownload()
を用意し、CRCに適当な値を渡すことでもキャッシュがクリアされる
この場合、通常のCacheOrDownloadにCRCの指定はいらない
WWW.LoadFromCacheOrDownload(rul, version, crc);
※Unity5.3になってからか、エラーが吐かれるようになったぽい?
CRC Mismatch. Provided 1, calculated 99199dcb from data. Will not load AssetBundle
ロードのリクエスト
バリアントを指定する。
バリアントに対応したアセットバンドルがある場合はそちらの名前でロードを行う
アセットバンドル名にさらにバリアントを使用するとそのアセットバンドル名内でバリアントが使用されていないアセットが登録されている場合はビルドエラーとなる
同名のアセットバンドル。片方にはバリアントがあるがもう片方にはNoneが設定されている場合別のアセットバンドル名と認識して、同名禁止のルールに抵触するため
アセットバンドル全体のキャッシュクリア
Caching.CleanCache();
を使用すればすぐに消える
アセットバンドルのキャッシュの状況
Caching.SpaceOccupied()
バイト単位のディスク使用量を返します
備考
- サーバーのURL アセットバンドル名がないとバリアントの指定ができない
- パス指定することにより階層を持ったアセットバンドル
参考
http://www.slideshare.net/MakotoItoh/unite2015-assetbundle-final