Help us understand the problem. What is going on with this article?

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

hinagawa
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした