【Unity】AddressableAssetSystemで、他のプロジェクトのAASが作ったAssetBundleを利用する
Addressableで他のプロジェクトが作成したAssetBundleを使用する方法についてです。
内容
- AssetBundleを「上書き」する場合は、ContentCatalogを上書きするだけでいい
- "AssetBundleに含まれるPrefab"が参照するスクリプトは利用する側に移植する
- AssetBundleを「追加」する場合は、ContentCatalogをロードしてResourceLocationsに追加
- Builtinshader assetbundleが重複する場合は、ビルドから外す
Addressableで他のプロジェクトが作成したAssetBundleを使用したい
他のプロジェクトのAddressableが作成したAssetBundleを 使用する というのであれば、実はそれ程難しくはありません。 ContentCatalogを他のプロジェクトが作った物に差し替えるだけです。
ただし、幾つか制限が追加されます。
- Play Mode Script の Fast Mode や Virtual Mode は使用できない。
- AssetReference系のAPIは使用できない
このあたりは完全にローカルにアセットが無いことが理由なので、仕方がないといえば仕方がないと言えます。
何にせよやってみようと思います。
なお今回はせっかくなので新しくリリースされたSDトーコちゃんズを使ってみました。Spring Boneが新型になり、ShaderもUTS2ベースになったので非常に良い感じです*1
SDトーコちゃんズ登場! « UNITY-CHAN! OFFICIAL WEBSITE
Addressableのビルド用プロジェクトを用意する
今回は「ビルド用」と「実行用」のUnity Projectを用意します。どちらもAddressableは導入している状態です。
まずビルド用では、普通にAddressableを用意する環境を用意して Build Player Content
します。
ビルドした後は、以下の内容をexport packageしておきます。
StreamingAssets
の中身・・・特にaaフォルダ
以下の内容- AssetBundleに含めたPrefabが使用しているscript全て
スクリプトはファイルのGUIDが同じ事、そしてハッシュが同じ(シリアライズ可能な設定が一致)なら、実装違っていても普通に使用できます。なので他のプロジェクト側でAssetBundleを使用したいならば、スクリプトも持っていく必要があります。
持っていくスクリプトはlink.xmlで確認するのが手っ取り早いです。
【Unity】AddressableでAssetBundleをビルドすると link.xml も自動で生成される - テラシュールブログ
Addressableでビルド済みAssetBundleを使用する
次にビルド済みのAssetBundleを他のプロジェクトで使用します。
先程Exportした Unitypackageを「AssetBundleを利用するUnityProject」にインポートします。
重要なのは2つ。ContentCatalogデータと、catalogと同じパスにAssetBundleを配置することです。CatalogデータにABへのパス等が含まれるので、この2つさえ移植できれば概ね何とかなります。
あとは play mode script
をpack mode
に設定すれば、他のAddressableが生成したAssetBundleを使用出来ます。
public class LoadAddress : MonoBehaviour { // Start is called before the first frame update void Start() { Addressables.Instantiate("Toko_sum"); } }
既存のAddressableを使いつつ、動的にカタログを追加する
既にローカルでAddressableを使用して云々している場合で、既存のプロジェクトに外部で作成したカタログを追加してみます。
例えば以下のような形でカタログを新しく追加出来ます。
using System.Collections; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Assertions; using UnityEngine.ResourceManagement.AsyncOperations; public class LoadAddress : MonoBehaviour { IEnumerator Start() { // Webから新しいカタログを取得。ファイルパスかURL var requestCatalog = Addressables.LoadContentCatalog("http://192.168.100.100:51879/catalog_extra.json.json"); yield return requestCatalog; Assert.AreEqual(AsyncOperationStatus.Succeeded, requestCatalog.Status); // カタログを追加 Addressables.ResourceLocators.Add(requestCatalog.Result); // 新しいカタログ上のキャラクターを取得 Addressables.Instantiate("Toko_sum"); } }
ただ、お互いに default shader
を保有しているためにAssetBundleがぶつかる事があるかもしれません。そういった場合は、ビルドスクリプトを少し書き換えてやります。
BuildScriptBase
を継承したクラスを作成し、BuildScriptPackedMode
の中身をほぼコピペで新しいビルドスクリプトを作ります。LinkXmlGeneratorなど一部internalがあったので Addressables System/Editor
フォルダ以下に配置しました。
コードの変更点として、Built in shaderを作るタスクをビルドタスク一覧からコメントアウトで排除します。
ScriptableObjectを作成し、Data Buildersに登録、あとはBuild Scriptをカスタマイズした物に変更します。
これでローカルでは普通にAddressableを使用しつつ、外部で任意にカタログを追加して云々が出来ました。外部アセット(キャラクターや演出等)は外部でビルドしつつ、UIや幾つかのエフェクト等はローカルAddressableAssetSystemを使うとかすると良いかもしれません。
感想
AddressableはContentCatalogにアセットへのパスが含まれるので、コレをなんとかすれば割と素直に動いてくれます。
まだ未確認ですが、ContentCatalogをリロードしたい場合、一旦全てのアセット/インスタンスをリリースしてからコンテンツカタログを再ロードとかすると良いんじゃないかなと思ってます。変更チェックには.hash
を使ってあげると良いかも。
ということで他のAASが使用したAssetBundleを使用してみましたが、Addressableは設計的には「全部のアセットを一つのプロジェクトに突っ込んで使う」「コンテンツ作成はFastモードで行い、CIでコンテンツ更新、動作確認は実機」だと思うので、ABを通さないと動作確認が出来なくなるモードは若干微妙な気分です。
関連
www.slideshare.net
www.slideshare.net
*1:インポート時にGUIDが変更されていなかったため、SD Unitychanが既にある場合はGUIDが重複して新しいSpringBoneが外れる現象が起こりました。