コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】Addressables でリモートカタログのダウンロードの通信に失敗したか確認する例

ソースコード

using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;

public class Example : MonoBehaviour
{
    // リモートカタログのダウンロードの通信に失敗した場合、
    // 以下のようなエラーや例外が発生するのでそれで確認できる
    // OperationException : CheckCatalogsOperation failed with the following errors:
    // TextDataProvider : unable to load from url : http://172.28.224.1:64480/catalog_1.0.0.hash
    // System.Exception: Content update not available.
    // OperationException : ChainOperation failed because dependent operation failed
    private static readonly string[] ERROR_MESSAGES =
    {
        "CheckCatalogsOperation failed with the following errors: ",
        "TextDataProvider : unable to load from url : ",
        "Content update not available.",
        "ChainOperation failed because dependent operation failed",
    };

    // ゲーム開始時に呼び出されます
    private async void Start()
    {
        // Addressables を初期化します
        await Addressables.InitializeAsync().Task;

        // カタログを更新します
        await UpdateCatalogs();
    }

    // カタログを更新します
    private static async Task UpdateCatalogs()
    {
        var isCommunicationError = false;

        // Addressables 内部でエラーや例外が発生した時に呼び出されます
        void OnLogMessageReceivedThreaded( string condition, string trace, LogType type )
        {
            // 既にエラーを検知している場合は無視します
            if ( isCommunicationError ) return;

            // 通常のログと警告ログは無視します
            if ( type == LogType.Log || type == LogType.Warning ) return;

            // 通信に失敗した系のメッセージならエラーとみなします
            isCommunicationError = ERROR_MESSAGES.Any( x => condition.Contains( x ) );

            // Addressables 内部でエラーや例外が発生した時に呼び出される関数を解除します
            Application.logMessageReceivedThreaded -= OnLogMessageReceivedThreaded;
        }

        // Addressables 内部でエラーや例外が発生した時に呼び出される関数を登録します
        Application.logMessageReceivedThreaded += OnLogMessageReceivedThreaded;

        // カタログを更新します
        var result = Addressables.UpdateCatalogs();

        // 更新が完了するのを待機します
        await result.Task;

        // Addressables 内部でエラーや例外が発生した時に呼び出される関数を解除します
        Application.logMessageReceivedThreaded -= OnLogMessageReceivedThreaded;

        if ( isCommunicationError )
        {
            Debug.LogError( "通信に失敗しました" );
            return;
        }

        Debug.Log( "成功" );
    }
}