Addressables.UpdateCatalogs() でカタログのアップデートに失敗しても try ~ catch をすり抜ける問題

発生した問題

サーバーに、新しいコンテンツカタログの 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 以降。

The coloring of this site is Dracula PRO🧛🏻‍♂️
This website uses the FontAwesome icons licensed under CC BY 4.0.

2020 GIGA CREATION