(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

AssetBundleとは【Unity】【AssetBundle】


このエントリーをはてなブックマークに追加

この記事でのバージョン
Unity 2017.1.1f1


はじめに

今回はUnityのAssetBundleについての記事です!


個人開発だとサーバを使わない事も多いので、AssetBundleという名前は聞いた事はあるけど、

使ったことはないし、よく知らない!みたいな方もいるかと思います。


かく言う私もそうだったんですが、ちょっと使う機会が出来たので

AssetBundleについて簡単に調べて見ました!


なお、記事中では以下のアセットを使っております。





AssetBundleとは

まずはAssetBundleとはなんぞや、という所からですが、

とりあえずUnityのマニュアルを見てみると以下のように書かれていました。

アセットバンドル はランタイムに読み込むプラットフォーム特有のアセット (モデル、テクスチャ、プレハブ、オーディオクリップ、シーン全体) を含むアーカイブファイルです。アセットバンドルは互いの依存関係を示すことができます。例えば、アセットバンドル A のマテリアルはアセットバンドル B のテクスチャを参照できます。ネットワークを使った効果的な配布のために、アセットバンドルはその使用の要件に応じてビルトインのアルゴリズムの中の 1 つで圧縮されます (LZMA と LZ4)。

アセットバンドルはダウンロードコンテンツ (DLC) に有用で、初期インストールサイズを削減し、エンドユーザーのプラットフォームのために最適化されたアセットを読み込み、ランタイムのメモリにかかる負担を軽減します。


ちょっと長いので、端的にまとめると

AssetBundleとはUnityのアセットを一つにまとめたモノという感じでしょうか。

用途は主にアセットをダウンロードして使うことです。


なお、ローカルに配置して使うことも、もちろん可能ですが、

ローカルに配置してまで使う意味があるかは微妙な所です。

実際に検証してみた限りiOSやPCでは有益ですが、Androidではむしろしない方が良さそうです。


AssetBundleの生成方法

説明だけだとイマイチ理解に欠けるので、AssetBundleを実際に使ってみましょう。


まずはAssetBundleの生成方法ですが、意外と簡単で、

Inspectorの左下からアセットにAssetBundle名を設定し、


f:id:kan_kikuchi:20171012070105j:plain


以下のようなコードを実行するだけ。

//AssetBundleを書き出す
BuildPipeline.BuildAssetBundles (
  "Assets/AssetBundle",              //出力先のディレクトリのパス(Assets外でも大丈夫)
  BuildAssetBundleOptions.None,      //ビルドの設定(無圧縮にしたり、強制的に再ビルドしたり)
  BuildTarget.StandaloneOSXUniversal //対象のプラットフォーム
);


そうすると同じAssetBundle名を設定されたアセットが、一つのAssetBundleとして出力されます。


f:id:kan_kikuchi:20171012071202j:plain


なお、AssetBundle名はディレクトリに設定する事も可能で、

その場合はディレクトリ内の全アセットが同じAssetBundle名になります。


AssetBundleの使い方

次に生成したAssetBundleをロードして使う方法です。

今回はローカルに配置して使ってみます。


ローカルで使う場合にはStreamingAssetsというディレクトリに配置しましょう。

StreamingAssets と呼ばれるフォルダーに配置したファイルはビルド先のプラットフォームの、特定のフォルダーにそのまま何も変換されない状態で保持されます。


なお、StreamingAssetsへのパスはApplication.streamingAssetsPathで取得できます。


実際にStreamingAssetに配置したAssetBundleをロードし、

AssetBundleに含まれるSpriteを取得したコードが以下のものです。

//AssetBundleをロード
string assetBundlePath  = Application.streamingAssetsPath + "/texture";
AssetBundle assetBundle = AssetBundle.LoadFromFile (assetBundlePath);

//AssetBundleからアセット(Sprite)を取得
Sprite sprite = assetBundle.LoadAsset<Sprite> ("character_53");

f:id:kan_kikuchi:20171012073909j:plain


生成の時と同様、意外と簡単に出来ました!


おわりに

この記事では、AssetBundleの概要という事でかなり大雑把にしか説明していないので、

AssetBundleが簡単で使いやすそうに見えたかもしれませんが、実際はかなり面倒だったりします。


というのも、以下のようにAssetBundleには注意点や問題点が色々あるからです。

  • AssetBundleを作成するのに結構時間が掛かる
  • プラットフォームごとに作成する必要がある
  • streamingAssets内は全てビルドに含まれる(全プラットフォームのAssetBundleを入れてはいけない)
  • 既にロードしているAssetBundleを再度ロードするとエラーが出る
  • 同じアセットが重複してAssetBundleに含まれることがある
  • AssetBundle同士に依存関係が出来る事がある(prefabとそれに含まれるtextureとか)
  • AssetBundle内のprefabから、GameObject以外のComponentを直接取得することは出来ない



さらにサーバを使うと、端末のローカルに保存した古いAssetBundleを消さなければならない等、

もっと面倒事が増えるので、余計に大変です。


上記の問題点のいくつかを解決するAssetBundleManagerやAssetBundleGraphTool

というモノもありますが、これはまたの機会に。