Unity
unity5
AssetBundle

Unity5 AssetBundleまとめメモ

More than 1 year has passed since last update.


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という風に書き込む

AssetBundle00.png

AssetBundle01.png

ビルドを実行すると、指定した出力先で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を同じアセットとして扱える仕組み


アセットバンドル名を登録するボタンの隣にある小さなボタンで設定を行う


小文字のみで指定するとファイル名の最後に拡張子がつけられる

AssetBundle03.png

AssetBundle02.png


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クラスの主な用途

CSharp

// すべてのアセットバンドル名を取得する

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

アセットが必要になったタイミングで要求を行い、そこでダウンロードが行われる

demo.zip


AssetBundleManager.cs

ロードが完了したアセットバンドルを管理する、アセットバンドル名をキーとした辞書


ロードを管理したWWWをUpdateで監視し、Errorがあったらm_DownloadingErrorsにキーをアセットバンドル名、valueにエラー内容を書き込む


ダウンロードが完了すれば、Disposeし辞書から削除するそして

CSharp

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()

バイト単位のディスク使用量を返します


備考


  1. サーバーのURL アセットバンドル名がないとバリアントの指定ができない

  2. パス指定することにより階層を持ったアセットバンドル


参考

http://www.slideshare.net/MakotoItoh/unite2015-assetbundle-final