🐥

【Unity】Addressablesのキャッシュの場所を整理する(catalog系ファイル・アセットバンドル別 & Win/Mac別)

恋愛メタバースMemoriaを運営するFlamers CTOの設楽(だーら)です。
今回は、UnityのAddressables使用時の、キャッシュの位置についてまとめます。

概要

  • UnityのAddressables使用時、キャッシュがローカルに保存されます。その位置を特定することで、デバッグなどがしやすくなります。
  • WindowsとMacや、UnityEditorとビルドファイルで挙動が異なる部分があるので整理します。
  • Addressablesのキャッシュには、catalog関連ファイルのキャッシュと、アセットバンドル自体のキャッシュがあり、それぞれで整理します。

環境

  • Unity 2021.3.7f1
  • Addressables 1.19.19

前提

  • Addressablesの設定において、クラウド(AWS S3)からアセットバンドルを取得する設定と指定としています。
  • Addressablesでのファイルの参照の流れは以下の様になっています。
  1. settings.jsonがカタログファイルの置き場所を指定する
  2. カタログファイル(catalog_xx.jsonと.hash)がアセットバンドルの依存関係等を記録しています。
  3. カタログファイルの指定の通りに、アセットバンドル(.bundleファイル)をダウンロードして展開します。
  • settings.jsonが起点で、これはキャッシュされるものではありません。また、このファイルがローカルにない場合はエラーとなります。
    • これは通常、以下の位置に置かれます(プラットフォームごとのディレクトリ)
    • Library/com.unity.addressables/aa/Windows/settings.json
  • カタログファイルとアセットバンドルはキャッシュの対象となります。
    • このキャッシュの位置は、後述しますが、settings.jsonによって設定されています。

アセットバンドル

  • アセットバンドルファイルのキャッシュの位置です。
  • WinではUnityEditorとビルドでキャッシュの場所が共通なので、たとえば実際のビルドが作ったキャッシュを、UnityEditorが利用できます(Macはそうではありません)。
マシン UnityEditor ビルド
Windows C:\Users\Name\AppData\LocalLow\Unity\CompanyName_ProductName ←同じ
mac ~/Library/Caches/Unity/CompanyName_ProductName ~/Library/Caches/com.CompanyName.ProductName

カタログファイル(catalog_xx.json/hash)

  • カタログファイルは、アセットバンドルとは別の位置にキャッシュされます。
  • カタログファイルは、settings.jsonの位置によって指定されています。
  • 以下のようなsettings.jsonで今回は設定しています。
settings.json
{
    "m_buildTarget": "StandaloneWindows64",
    "m_SettingsHash": "",
    "m_CatalogLocations": [
        {
            "m_Keys": [
                "AddressablesMainContentCatalogRemoteHash"
            ],
            "m_InternalId": "https://xxxxxxxxxxx.s3.ap-northeast-1.amazonaws.com/StandaloneWindows64/catalog_xxxxxxxxxxxxx.hash",
            "m_Provider": 
...略...
        },
        {
            "m_Keys": [
                "AddressablesMainContentCatalogCacheHash"
            ],
            "m_InternalId": "{UnityEngine.Application.persistentDataPath}/com.unity.addressables/catalog_yyyyyyyyyyyyyyyyy.hash",
            "m_Provider":
...略...
        },
        {
            "m_Keys": [
                "AddressablesMainContentCatalog"
            ],
            "m_InternalId": "{UnityEngine.AddressableAssets.Addressables.RuntimePath}/catalog.json",
            "m_Provider": "UnityEngine.AddressableAssets.ResourceProviders.ContentCatalogProvider",
            "m_Dependencies": [
                "AddressablesMainContentCatalogRemoteHash",
                "AddressablesMainContentCatalogCacheHash"
            ],
            "m_ResourceType": {
                "m_AssemblyName": "Unity.Addressables, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
                "m_ClassName": "UnityEngine.AddressableAssets.ResourceLocators.ContentCatalogData"
            },
            "SerializedData": []
        }
    ],
  • 上記のsettings.jsonのKeyの役割は以下だと把握しています。
    • AddressablesMainContentCatalogRemoteHash: 一番最初に見に行くリモートの場所
    • AddressablesMainContentCatalogCacheHash: 上記のリモートの場所から取得したカタログファイルをキャッシュする場所
    • AddressablesMainContentCatalog: 上記2箇所に無い場合に参照される場所(リモート取得したカタログファイルが自動でキャッシュされはしない)
  • それぞれの保存場所はプラットフォームごとに以下のようになっています。

AddressablesMainContentCatalogCacheHash

  • UnityEngine.Application.persistentDataPathで出力
マシン UnityEditor ビルド
Windows C:/Users/name/AppData/LocalLow/CompanyName/ProductName ←同じ
mac /Users/name/Library/Application Support/CompanyName/ProductName ←同じ

AddressablesMainContentCatalog

  • UnityEngine.AddressableAssets.Addressables.RuntimePathで出力
マシン UnityEditor ビルド
Windows Library/com.unity.addressables/aa/Windows (ビルドファイルの.exeのあるディレクトリの絶対パス)/ProductName_Data/StreamingAssets/aa
mac Library/com.unity.addressables/aa/OSX (ビルドファイルの.appの絶対パス)/Contents/Resources/Data/StreamingAssets/aa

(補足)各所のカタログファイルの有無による実験

  • カタログファイル(catalog_xx.json/hash)が、それぞれの位置に有る/無いの条件ごとに、アセットバンドルが読み込めてsceneが展開されるかを実験します。
  • S3: AWSのS3
  • リモートキャッシュ: AddressablesMainContentCatalogCacheHashの場所
  • ローカル: AddressablesMainContentCatalogの場所

実験1

S3 リモートキャッシュ ローカル 結果
有り 無し 無し 読み込めた
  • さらに、リモートキャッシュにキャッシュが作成された。
  • キャッシュのファイル名は、catalog_xx.jsonとcatalog_xx.hashで生成されている。(S3に上がっているものと同じ)

実験2

S3 リモートキャッシュ ローカル 結果
有り 有り 無し 読み込めた
  • キャッシュは置き換わらない(作成日時は実験1と同じ時間で更新されていない)

実験3

S3 リモートキャッシュ ローカル 結果
無し 有り 無し 読み込めた
  • キャッシュは引き続き置き換わっていない

実験4

S3 リモートキャッシュ ローカル 結果
無し 無し 無し 読み込めない
  • 以下のようなエラーが発生
System.Exception: Invalid path in TextDataProvider : 'Library/com.unity.addressables/aa/Windows/catalog.json'.
UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1/<>c__DisplayClass57_0<System.Collections.Generic.IList`1<UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle>>:
...略...
Library/PackageCache/com.unity.addressables@1.19.19/Runtime/ResourceManager/Util/DelegateList.cs:69)
UnityEngine.AsyncOperation:InvokeCompletionEvent ()

実験5

S3 リモートキャッシュ ローカル 結果
無し 無し 有り 読み込めた
  • S3に上げていたcatalog_xx.jsonを、catalog.jsonに改名してから、Libraryの中に保存する
  • S3にもキャッシュにもなくても、読み込める事がわかる

補足: キャッシュのファイル名と、S3のBundleの名前との関係

  • S3で
    ...StandaloneWindows64/remotegroup_scenes_assets/flamers/scenes/〇〇.unity_△△△△.bundle
  • キャッシュで
    AppData/LocalLow/Unity/Flamers_MemoriaVR/■■■/△△△△
    〇〇はscene名、△△は英数字の羅列、■■■は英数字の羅列
Flamers Tech Blog

Discussion