はじめに
以前Addressable Asset System
についての基本操作の記事を書いたのですが、Asset Bundle
の知識もマトモに得ずにけしからんと怒られてしまうかもしれないのでAsset Bundle
の基礎を学んでいこうかなと思います。(Addressable
は内部的にAssetBundle
を利用している)
www.hanachiru-blog.com
また公式ドキュメントはこちら。
docs.unity3d.com
概要
Asset Bundle
についての説明を公式ドキュメントより引っ張ってきます。
AssetBundle (アセットバンドル) はランタイムに読み込むプラットフォーム特有のコード以外のアセット (モデル、テクスチャ、プレハブ、オーディオクリップ、シーン全体) を含むアーカイブファイルです。アセットバンドルは互いの依存関係を示すことができます。例えば、あるアセットバンドル のマテリアルは他のアセットバンドルのテクスチャを参照できます。ネットワークを使った効果的な配布のために、アセットバンドルはその使用要件に応じてビルトインのアルゴリズムの中の 1 つで圧縮されます (LZMA と LZ4)。
アセットバンドルはダウンロードコンテンツ (DLC) に有用で、初期インストールサイズを削減し、エンドユーザーのプラットフォームのために最適化されたアセットを読み込み、ランタイムのメモリにかかる負担を軽減します。
AssetBundle
に格納するアセットとしてモデル、テクスチャ、プレハブ、オーディオクリップ、シーン全体が紹介されていますが、ScriptableObject
を格納することもできます。ただScriptableObject
を定義している.cs
ファイル自体はプロジェクトのアセンブリに含まれていなければならないことに注意してください。
利用の流れ
Asset Bundle
を利用するにあたって以下のフローを行います。
- アセットバンドルにアセットを割り当てる
- アセットバンドルをビルドする
- アセットバンドルとアセットをロードする
またAsset Bundle
は必ずリモートからダウンロードしなければならないわけではなく、ローカルに配置することもできます。
- サーバーに配置した
Asset Bundle
をダウンロードして利用する StreamingAssets
内に配置したAsset Bundle
を読み込んで利用する
後気をつけてほしい点としてBuildTarget
というどのプラットフォーム向けにビルドするか設定しなければならず、指定したプラットフォーム以外だと利用できないことも注意してください。
- StandaloneOSX
- StandaloneWindows
- iOS
- Android
- StandaloneWindows64
- WebGL
- WSAPlayer
- StandaloneLinux64
- PS4
- XboxOne
- tvOS
- Switch
- Stadia
- CloudRendering
- PS5
BuildTarget - Unity スクリプトリファレンス
加えて圧縮の仕方を指定することができ、以下の3つから選びます。(LZ4
を利用する方が多いよう)
- 非圧縮
- LZMA
- LZ4
アセットバンドルにアセットを割り当てる
Project
ビューより対象のアセットを選択し、Inspector
ビューの下部にAsset Bundle
と書かれた左にあるセクションをクリック、New
よりアセットバンドル名を指定します。
このときSampleFolder/Sample
のように/
をつけることでフォルダー構造にすることができます。
アセットバンドルをビルドする
アセットバンドルをビルドするにはコードを書かなければいけません。正直めんどくさいですが、サンプルを公式ドキュメントより引用させていただきます。
using UnityEditor; using System.IO; public class CreateAssetBundles { [MenuItem("Assets/Build AssetBundles")] static void BuildAllAssetBundles() { string assetBundleDirectory = "Assets/AssetBundles"; if(!Directory.Exists(assetBundleDirectory)) { Directory.CreateDirectory(assetBundleDirectory); } BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows); } }
https://docs.unity3d.com/jp/current/Manual/AssetBundles-Workflow.html
コードの説明をざっくりするとこんな感じ。
MenuItem
でUnityの上にあるメニューバーにあるAssets/Build AssetBundles
を選択することで、メソッドを実行するAssets/AssetBundles
フォルダ内にビルド後のファイルを出力するBuildPipeline.BuildAssetBundles
でビルドを行う
BuildPipeline.BuildAssetBundles
の引数は結構色々と設定することができます。
Unity - スクリプティング API: BuildPipeline.BuildAssetBundle
一番気をつけてほしいのは前述もしましたがBuildTarget
で、適切なものを選択してください。
またBuildAssetBundleOptions.None
に関しては以下の記事が参考になるかと。
アセットバンドルのビルド - Unity マニュアル
ビルドされたファイル群
AssetBundles |--- AssetBundles |--- AssetBundles.manifest |--- samplefolder |--- sample |--- sample.manifest
Manifestファイル
上記のAssetBundles.manifest
とsample.manifest
の中身を覗いてみましょう。
// sample.manifest ManifestFileVersion: 0 CRC: 307180686 Hashes: AssetFileHash: serializedVersion: 2 Hash: 46b1de024bbcb1a0d43b0604c3474f58 TypeTreeHash: serializedVersion: 2 Hash: 4df8c69f2c8a6ad9e3cbf82bb83e4dc3 HashAppended: 0 ClassTypes: - Class: 28 Script: {instanceID: 0} - Class: 213 Script: {instanceID: 0} SerializeReferenceClassIdentifiers: [] Assets: - Assets/Sprites/AssetBundle/assetbundle.png Dependencies: []
sample.manifest
には含まれるアセット、依存関係等の情報が書き込まれています。
// AssetBundles.manifest ManifestFileVersion: 0 CRC: 1670162852 AssetBundleManifest: AssetBundleInfos: Info_0: Name: samplefolder/sample Dependencies: {}
対してAssetBundles.manifest
にはアセットバンドルの関連情報と依存関係を表しています。
またドキュメントにmanifest
ファイルの読み込み方・利用の仕方の紹介がされていますね。
アセットバンドルを使いこなす - Unity マニュアル
AssetBundle ファイル
AssetBundles
とsample
がAssetBundle
ファイルに該当します。
アセットバンドルファイルは複数のファイルを内部に持つアーカイブであり、バイナリデータです。
またAsset Bundle
ファイルに何が含まれるかについては以下のような説明がありました。
- シリアル化したファイル。個々のオブジェクトに分割され、この 1 つのファイルに書き出されたアセットが含まれています
- リソースファイル。特定のアセット (テクスチャとオーディオ ) 用に別々に格納されたバイナリデータのチャンクで、Unity が別のスレッドのディスクから効率的にロードできるようにします。
アセットバンドルとアセットをロードする
今回は分かりやすくローカルのStreamingAssets
からロードを行なってみます。
StreamingAssets
フォルダを作成し、先ほどビルドしたファイル群を移動させます。
サンプルを参考にしながらコードを作成しました。
using System.IO; using UnityEngine; using UnityEngine.UI; public class LoadFromFileExample : MonoBehaviour { [SerializeField] private Image image; private void Start() { // AssetBundleのメタ情報のロード var assetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "samplefolder/sample")); if (assetBundle == null) { Debug.Log("Failed to load AssetBundle!"); return; } // テクスチャをメモリにロード var sprite = assetBundle.LoadAsset<Sprite>("assetbundle"); image.sprite = sprite; // AssetBundleのメタ情報をアンロード assetBundle.Unload(false); } }
また今回はAssetBundle.LoadFromFile
を利用しましたが、以下の4種類が存在します。
- AssetBundle.LoadFromMemoryAsync
- AssetBundle.LoadFromFile
- WWW.LoadfromCacheOrDownload
- UnityWebRequestAssetBundle の DownloadHandlerAssetBundle (Unity 5.3 以降のもの)
詳しくは上記記事を参照してみてください。
ひとこと
AssetBundle
の基本しか触れませんでしたが、Unload
であったり依存解決であったりと難しい箇所がまだまだ潜んでいます。
qiita.com
今から利用するのであればUnity公式がAddressable Asset System
を用意してくれているので、特に理由がなければそちらを使っていけば良いとは思います。