発生した問題
サーバーに、新しいコンテンツカタログの hash だけあり、json は無いという状況で Addressables.UpdateCatalogs()
を実行すると、エラーは発生するもののなぜか try ~ catch をすり抜けてしまう。
try { // これがエラーになっても…… await Addressables.UpdateCatalogs(); } catch { // ここに到達しない Debug.LogError("コンテンツカタログのアップデートに失敗しました。"); }
解決方法
アップデートに失敗した場合、Result の List<IResourceLocator>
が空なので、以下のようにリストの中身の有無で成功したかどうかを判断する。
// カタログをアップデートする List<IResourceLocator> locators = await Addressables.UpdateCatalogs(); // リストが空なら失敗扱いにする if (!locators.Any()) { Debug.LogError("コンテンツカタログのアップデートに失敗しました。"); }
説明
新しいコンテンツカタログのハッシュが見つかった時点で、 Addressables.UpdateCatalogs()
は成功扱いになるようです。返ってくる AsyncOperationHandle の Status も Succeeded
になります。なぜ……。
AsyncOperationHandle の Result にはアップデートされたカタログの IResourceLocator のリストが入るのですが、実際にはカタログのアップデートには失敗しているので、空のリストが入ってきます。なのでこのリストの中身を見れば、本当にカタログがアップデートできたのかが判断できます。
補遺
Addressables.UpdateCatalogs(true)
というように第一引数に true
を指定すると、カタログのアップデート後に使われなくなったアセットバンドルのキャッシュの削除を行ってくれます。*1
通常、カタログのアップデートが行われないとキャッシュの削除も行われないのですが、今回のように実際は失敗していても内部的には成功扱いになってしまっている場合、キャッシュの削除処理も走ってしまい、以下のエラーが発生します。
OperationException : UnityEngine.AddressableAssets.CleanBundleCacheOperation, result='', status='Failed', status=Failed, result=False catalogs updated, but failed to clean bundle cache.
現状、これを回避する方法は無さそうなので、以下のようにアップデートが本当に成功したかどうかを確認してから別途キャッシュクリアを行うようにするのが良いでしょう。
// カタログをアップデートする List<IResourceLocator> locators = await Addressables.UpdateCatalogs(); // リストが空なら失敗扱いにする if (!locators.Any()) { Debug.LogError("コンテンツカタログのアップデートに失敗しました。"); // 処理を打ち止め return false; } // キャッシュをクリアする Addressables.CleanBundleCache();
*1:バージョン 1.19.4 以降。