AssetBundle (アセットバンドル) のロードには 4 種類の API を使用できます。それらの動作は、バンドルがロードされるプラットフォームと、アセットバンドルのビルドに使用された圧縮方法 (非圧縮、LZMA、LZ4) によって異なります。
以下の 4 つの API があります。
AssetBundle.LoadFromMemoryAsync
この関数は、該当のアセットバンドルのデータを含むバイトの配列を 1 つ取得します。必要であれば CRC 値を 1 つ渡すことも可能です。バンドルが LZMA 圧縮されていれば、そのアセットバンドルはロード中に解凍されます。LZ4 圧縮されたバンドルは圧縮された状態のままロードされまれます。
以下は、このメソッドの使用方法の一例です。
using UnityEngine;
using System.Collections;
using System.IO;
public class Example : MonoBehaviour
{
IEnumerator LoadFromMemoryAsync(string path)
{
AssetBundleCreateRequest createRequest = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
yield return createRequest;
AssetBundle bundle = createRequest.assetBundle;
var prefab = bundle.LoadAsset<GameObject>("MyObject");
Instantiate(prefab);
}
}
ただし LoadFromMemoryAsync は他の方法でも使用できます。 File.ReadAllBytes(path) は、バイト配列のどんな取得方法にでも置き換えることができます。
この API は、非圧縮バンドルをローカルストレージからロードする際に使用すると非常に効率的です。 LoadFromFile は、バンドルが非圧縮の場合やチャンクベースの圧縮方式 (LZ4) で圧縮されている場合に、ディスクから直接バンドルをロードします。完全圧縮 (LZMA) バンドルをこのメソッドでロードする場合は、バンドルが解凍されてからメモリにロードされます。
以下は LoadFromFile
の使用方法の一例です。
using System.IO;
using UnityEngine;
public class LoadFromFileExample : MonoBehaviour
{
void Start()
{
var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
if (myLoadedAssetBundle == null)
{
Debug.Log("Failed to load AssetBundle!");
return;
}
var prefab = myLoadedAssetBundle.LoadAsset<GameObject>("MyObject");
Instantiate(prefab);
}
}
ノート: Android デバイスで、 バージョン 5.3 またはそれ以前の Unity を使用している場合、この API で Streaming Assets パスからアセットバンドルを呼び出そうとすると失敗します。これは、このパスのコンテンツが圧縮 .jar ファイル内に存在しているためです。 Unity 5.4 以降では、Streaming Assets にも API コールを問題なく使用できます。
UnityWebRequestAssetBundle には、アセットバンドル専用の API コールがあります。これを開始するには、UnityWebRequestAssetBundle.GetAssetBundle
を使用してウェブリクエストを作成する必要があります。リクエストを返した後に、そのリクエストオブジェクトを DownloadHandlerAssetBundle.GetContent(UnityWebRequestAssetBundle)
に渡します。この GetContent
の呼び出しがアセットバンドルオブジェクトを返します。
また、バンドルのロード後に DownloadHandlerAssetBundle クラスの assetBundle
プロパティを使用することで、 AssetBundle.LoadFromFile
の効率性をもってアセットバンドルをロードすることができます。
以下の例では、2 つのゲームオブジェクトを含むアセットバンドルをロードし、それらをインスタンス化しています。この処理は StartCoroutine(InstantiateObject())
; を呼び出すだけで開始できます。
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequestAssetBundle request
= UnityEngine.Networking.UnityWebRequestAssetBundle.GetAssetBundle(uri, 0);
yield return request.SendWebRequest();
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");
Instantiate(cube);
Instantiate(sprite);
}
アセットバンドルのダウンロードに成功したら、アセットのロードを開始することができます。
汎用コード スニペット
T objectFromBundle = bundleObject.LoadAsset<T>(assetName);
T は、ロードするアセットのタイプです。
アセットのロード方法はいくつかあります。 LoadAsset
と LoadAllAssets
および、それらの Async バージョンである LoadAssetAsyncと
LoadAllAssetsAsync` です。
アセットバンドルから同期的にアセットをロードする方法は以下の通りです。
単一のゲームオブジェクトをロードするには以下を使用します。
GameObject gameObject = loadedAssetBundle.LoadAsset<GameObject>(assetName);
全てのアセットをロードするには以下を使用します。
Unity.Object[] objectArray = loadedAssetBundle.LoadAllAssets();
上述のメソッドはロードするオブジェクトのタイプかオブジェクトの配列を返しますが、非同期メソッドは AssetBundleRequest を返します。アセットへのアクセスは、この処理が完了するのを待ってから行う必要があります。アセットは以下を使用してロードできます。
AssetBundleRequest request = loadedAssetBundleObject.LoadAssetAsync<GameObject>(assetName);
yield return request;
var loadedAsset = request.asset;
または
AssetBundleRequest request = loadedAssetBundle.LoadAllAssetsAsync();
yield return request;
var loadedAssets = request.allAssets;
アセットのロードが終わったら、準備完了です。ロードされたオブジェクトを、その他のオブジェクトと同じように Unity 上で使用することができます。
アセットバンドル マニフェストをロードすると非常に役立ち得ます。特にアセットバンドルの依存関係を扱う場合には有益です。
使用可能な AssetBundleManifest オブジェクトを取得するには、追加のアセットバンドル (その格納されているフォルダーと同じ名前のアセットバンドル) をロードし、 AssetBundleManifest タイプのオブジェクトを 1 つ、そこからロードする必要があります。
マニフェスト自体のロードは、その他通常のアセットをアセットバンドルからロードする場合と全く同じように行われます。
AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
これで、上記の例にあるマニフェストオブジェクトによって AssetBundleManifest
API コールが使用できるようになりました。ここからは、ビルドしたアセットバンドルの情報を、マニフェストを使用して取得することができます。この情報には、該当のアセットバンドルの依存関係データ、ハッシュデータ、バリアントデータが含まれます。
先の “アセットバンドルの依存関係” の項で、“あるバンドルが別のバンドルに依存関係をもつ場合は、それらのバンドルは、元のバンドル内のアセットをロードする前にロードする必要がある” ことを述べました。マニフェストオブジェクトは、ロード中の依存関係を動的に見つけることを可能にします。例えば、“assetBundle” という名前のアセットバンドルの依存関係を全てロードしたいと仮定しましょう。
AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
string[] dependencies = manifest.GetAllDependencies("assetBundle"); //依存関係を取得するバンドル名を渡します
foreach(string dependency in dependencies)
{
AssetBundle.LoadFromFile(Path.Combine(assetBundlePath, dependency));
}
これでアセットバンドル、アセットバンドルの依存関係、アセットのロードが完了しました。次は、ロードしたアセットバンドルの管理についての解説です。
ノート: Addressable Assets パッケージは、アセットバンドル、依存関係、アセットのロードを管理するための既製のシステムを提供します。Unity は、アセットバンドルを自分で管理するよりも Addressable を使うことを推奨します。
Unity Learn の ロードされたアセットバンドルの管理に関するチュートリアル も参照してください。
Unity は、アクティブなシーンから削除されたオブジェクトを自動的にアンロードしません。アセットのクリーンアップは特定の時点でトリガーされますが、手動でトリガーすることも可能です。
アセットバンドルのロードとアンロードを行うタイミングを把握することが重要です。アセットバンドルの不適切なアンロードは、メモリ内におけるオブジェクトの重複やテクスチャの欠落など、望ましくない結果を引き起こす可能性があります。
アセットバンドルの管理について理解すべき最大のポイントは、AssetBundle.Unload(bool) – またはAssetBundle.UnloadAsync(bool) – をいつ呼び出すか、そして関数呼び出しに true または false を渡すべきかということです。 Unload は、アセットバンドルをアンロードする静的ではない関数です。この API は、呼び出されるアセットバンドルのヘッダー情報をアンロードします。引数は、このアセットバンドルからインスタンス化されたすべてのオブジェクトもアンロードするかどうかを示します。
AssetBundle.Unload(true)
は、アセットバンドルからロードしたすべてのオブジェクト (とその依存関係) をアンロードします。これには、コピーしたゲームオブジェクト (インスタンス化したゲームオブジェクトなど) は含まれません。それらはもはや、アセットバンドルには属さないからです。AssetBundle.Unload(true) を呼んだとき、アセットバンドルからロードされ、かつ、まだアセットバンドルに属しているテクスチャは、シーンのゲームオブジェクトから消滅します。Unity はこれを欠落したテクスチャとして扱います。
下の図のようにアセットバンドル AB からマテリアル M がロードされ、プレハブ P で使用されるとします。
AB.Unload(true) が呼び出されると、アクティブシーン内の M のインスタンスも全てアンロードされ、破棄されます。
一方、 AB.Unload(false) を呼び出した場合、現在の M および AB のインスタンスのチェーンが破壊されます。
後で AB が再度ロードされ AB.LoadAsset() が呼び出されても、Unity は既存の M のコピーを新しくロードされたマテリアルに再リンクしません。
プレハブ P の別のインスタンスを作成すると、既存の M のコピーは使用されず、代わりに M の 2 つのコピーがロードされます。
一般的に、AssetBundle.Unload(false)
を使用しても、理想的な状況にはなりません。ほとんどのプロジェクトで、AssetBundle.Unload(true)
を使用し、オブジェクトが重複しない方法を採用するべきです。一般的な方法は 2 つあります。
アプリケーションのライフタイム内で、一時的なアセットバンドルをアンロードする丁度良いタイミングを設定する。例えばステージとステージの間やロード画面など。
個々のオブジェクトの参照カウントを維持し、アセットバンドルに含まれるオブジェクトがひとつも使用中でない場合にのみ、アセットバンドルをアンロードする。この方法だと、メモリの重複を起こすことなく、アプリケーションのオブジェクトを個々にアンロードおよびリロードできます。
どうしても AssetBundle.Unload(false)
の使用が必要なアプリケーションの場合、個々のオブジェクトをアンロードする方法は次の 2 つのみになります。
不要なオブジェクトへの参照を、シーン内とコード内の両方で削除し、その後 Resources.UnloadUnusedAssets を呼び出す。
非加算的にシーンをロードする。これにより、現在のシーン内の全てのオブジェクトが破棄されて Resources.UnloadUnusedAssets が自動的に実行されます。
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.