Addressableについて調べていたらもうこんな時間です。
アセットバンドルのビルドに数時間かかる事例を目にしたので、何かいい方法がないか調べていると、Addressableのカタログは分割が可能であるという情報をいくつか見つけました。
Addressables.LoadContentCatalogAsyncにカタログが置いてあるURLを渡すことで、カタログをロードすることができるそうです。
カタログのロード後は通常通りAddressables.LoadAssetAsyncなどでアセットのロードが可能になります。
「unity addressable カタログ 分割」で検索すると他にもいくつか出てきます。
しかし、この関数を使えばよいといった情報ばかりで、実例を見つけられなかったため、自分の想像している通りのことが可能か実際に試してみました。
(本当は、同じカタログの一部のアセットだけをビルドできれば良いのですが)
環境
Unity: 6000.0.38f1
Addressables: 2.2.2
アセットバンドル格納先: aws s3(CloudFront)
各種設定
awsについて
本筋ではないので簡潔に。
参考にしたリンクと自分用の手順メモを貼っておきます。
(お金がかかる可能性があります。)
手順メモ
- s3設定
推奨設定でバケットを作成
ブロックパブリックアクセス設定だけオフに変更 - CloudFront設定
Origin domain...作成したs3のバケットを設定
オリジンアクセス...Legacy access identitiesを指定し、オリジンアクセスアイデンティティで新しいOAIを作成
バケットポリシーを自動で更新する
キャッシュビヘイビア...ビューワープロトコルポリシーをRedirect HTTP to HTTPSに変更
キャッシュキーとオリジンリクエスト...キャッシュポリシーをCachingDisableに変更(ここはCloudFrontのキャッシュ削除ができるようになったら、そのままにしてよさそう)
ウェブアプリケーションファイアウォール (WAF) ...お金がかかるので、いったんオフ
料金クラス...北米、欧州、アジア、中東、アフリカを使用
Addressablesについて
Unityプロジェクトを新規作成してPackageManagerからAddressablesをインストールしたら、Settingsなどの設定を行います。
-
Addressables Profiles
プロファイルを3つ作成し、RemoteのBuildPathとLoadPathを変更します。
BuildPathには、ServerData/data1/[BuildTarget]
LoadPathには、https://{Remote.RemoteURL}.cloudfront.net/AssetBundle/[BuildTarget]
を設定します。
各プロファイルでdata1、data2、data3とAssetBundle、AssetBundle2、AssetBundle3と設定します -
Addressable Asset Settings
- Addressables Groups
FirstGroup、SecondGroup、ThirdGroupを作成し、それぞれ画像アセットを1つずつ追加します。
Addressable Asset Groupなどの設定は、下の画像を参考にしてください。3種類とも同じ設定です。
実験準備
アセットのビルド
グループごとにアセットのビルドを行います。
必要な作業はAddressables Profilesウィンドウからプロファイルを切り替えることと、
Addressable Asset GroupのInclude In Buildを切り替えることです。
プロファイルごとに、Include In Buildのチェックが入っているアセットグループが一つだけになるように切り替えます。
切り替えたら、Addressables GroupsウィンドウのBuild->New Buildからビルドします。これを各プロファイルで行います。
ビルドが完了すると、Assetsなどのフォルダの並びにServerDataフォルダが作成されます。
ServerDataフォルダの中には、BuildPath通りにAssetBundleが配置されているので、それぞれ対応するLoadPath通りにs3へアップロードします。
プロジェクトのビルド
画像のようなシーンを用意しました。catalogボタンでカタログを、imageボタンで対応するカタログの画像をロードし、表示します。
catalogボタンに設定した関数
public class AddressableTest : MonoBehaviour
{
[SerializeField] TextMeshProUGUI text;
string cloudFrontPath = "https://" + Remote.RemoteURL + ".cloudfront.net/";
string[] bundlePaths = { "AssetBundle", "AssetBundle2", "AssetBundle3" };
string catalogPath = "/StandaloneWindows64/catalog_0.1.0.json";
public void LoadCatalog(int number)
{
string path = bundlePaths[number] + catalogPath;
Addressables.LoadContentCatalogAsync(cloudFrontPath + path, true);
text.text = "Load " + path;
}
}
実験
catalog1を押下し、それからimage1を押下する
=> FirstGroupに設定した画像が表示される
catalog2を押下せずにimage2を押下する
=> キーが存在しないというエラーが表示され、画像が読み込まれなかった時用の画像が表示される
catalog2を押下してから、image2を押下する
=> SecondGroupに設定した画像が表示される
アプリを一度再起動
catalog3を押下せずにimage3を押下する
=> なぜかThirdGroupに設定した画像が表示される
=> settings.jsonを確認すると、AssetBundle3のカタログがデフォルトになっていた
まとめ
LoadContentCatalogAsyncを使うことで、catalog(アセットバンドル)を分割しても、問題なくアセットをロードすることができました。
一点注意があり、アセットバンドルを分割した場合、分割をまたいで参照を持つことができなくなるそうです。この点は意識してアセットを分割するしかないです。(あるいは解決方法を探すか)
また、プロファイルとアセットグループの切り替えを手動で行うのはかなり面倒です。
そのため、エディター拡張などを行い、手軽に運用できる環境を整えていく必要がありそうです。