【Unity】Addressable Asset SystemでRemote運用を考えてみた

AddressableAssetSystem

この記事は Unity Advent Calendar 2021#2 13日目の記事です。

AddressableAssetSystemのRemote運用
主にRemoteアセットに別途バージョンを付けての更新する方法について考えてみました

検証環境

  • Unity2020.3.15f1
  • Addressable Asset System 1.18.11

各アセットの格納先について

以下2種類のみ

  • Local
    • アプリ内に内包する用のアセットはこちらを指定する
  • Remote
    • アプリ外(サーバー)にファイルを配置し、動的にダウンロードして使用するアセットはこちらを指定する

ビルドされたアセットのバージョン

  • Catalog.jsonファイルに記載されている
  • 標準だとビルド時のtimestampがファイル名に追記される
  • AddressableAssetSettingsのPlayerVersionOverrideを使用するとその文字列がファイル名に

アプリ想定

今回想定するアプリは以下のような環境を想定する。
だいたいよくみるやつです。

  • アセットはアプリに内包するもの(Local)とアプリ外(サーバー)に配置するもの(Remote)の2種類ある
  • アセット自体にもアプリとは別にバージョン管理する(Ver.1.0.1等)
  • アプリの更新はなくRemoteアセットの更新のみもある(画像の更新等)

想定を満たす為の構想案

  • アプリビルド時にはLocal対象のアセットだけビルドする
    アプリに内包されるCatalog.jsonはLocalのものしかない状態
  • アセットビルド時にはRemote対象のアセットだけビルドする
    Catalog.jsonにはRemoteのものしかない状態
  • Remoteのアセットの際には別途バージョン管理を行う
  • アセットDLにはRemote用のCatalog.jsonを取得しそれを元にアセットをDLする

Remoteもアプリ内包のCatalog.jsonを使用するようにするとアプリビルド時のバージョンと同じものしか使用することができず別途バージョン管理を行えない為この形に

構想案を実施するためのシステム設計

■AddressableAssetSystemのProfile設定

  • 新規Variable「AssetVersion」を追加する
  • RemoteBuildPathとRemoteLoadPathに先ほど追加した「AssetVersion」をフォルダになるよう追記する

■アセットビルド

アプリビルド時およびアセットビルド時にそれぞれLocalかRemoteしかビルドしようにBuildScript作成
isRemoteはアプリビルド時にはfalse、Remote用のアセットビルド時にはtrueが入る

public static void BuildAsset(string profileID, string version, bool isRemote)
{
   var settings = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEditor.AddressableAssets.Settings.AddressableAssetSettings>(
      "Assets/AddressableAssetsData/AddressableAssetSettings.asset"
   );

   var profileId = settings.profileSettings.GetProfileId(profileID);
   settings.activeProfileId = profileId;
   settings.BuildRemoteCatalog = isRemote;
   // 追加したVariable「AssetVersion」にバージョンを指定する
   settings.profileSettings.SetValue(settings.activeProfileId, "AssetVersion", version);
   
   // 各グループごとにビルドするものを指定する
   foreach (var group in settings.groups)
   {
      var schema = group.Schemas[0] as BundledAssetGroupSchema;
      // LoadPathにRemoteかLocalの文字が含まれているかで判定する
      schema.IncludeInBuild = schema.LoadPath.GetName(settings).Contains(isRemote ? "Remote" : "Local");
   }
   
   var context = new AddressablesDataBuilderInput(settings, version);
   settings.ActivePlayerDataBuilder.BuildData<AddressablesPlayerBuildResult>(context);
}

■アセットダウンロード

アプリからのアセットダウンロードはLoadContentCatalogAsyncを使用し
Remote分だけ追加する

       public AsyncOperationHandle<IResourceLocator> LoadContentCatalogAsync(string version)
      {
#if UNITY_IOS
         string PlatformPath = "iOS";
#else
         string PlatformPath = "Android";
#endif
         string RemoteServer = "Http://hogehoge";
         
         string address = $"{RemoteServer}/{PlatformPath}/{version}/catalog_{version}.json";
         var handle = Addressables.LoadContentCatalogAsync(address);
         return handle;
      }

これで引数のversionにダウンロードしたいバージョンを指定してダウンロードする
多分サーバーからログイン時等にバージョンを受け取ってそちらを指定するイメージ

最後に

これで、Remoteアセットに別途バージョンを付けての更新する運用が可能になりそうです。
また、RemoteServerの部分も別途変更できるようにし、Remoteアセットの格納先をしっかり運用すれば開発用でチェックしたアセットをもう1回ビルドすることなく本番でも使用するといった事も可能になりそう。
このあたりで悩んでいた人の何かしらのきっかけになれば幸いです。

コメント

タイトルとURLをコピーしました