コガネブログ

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

【Unity】FirestoreException: Failed to get document because the client is offline.

はじめに

using Firebase.Firestore;
using UnityEngine;

public class Example : MonoBehaviour
{
    private async void Start()
    {
        var firestore = FirebaseFirestore.DefaultInstance;

        var documentReference = firestore
                .Collection( "users" )
                .Document( "players" )
            ;

        var snapshot = await documentReference.GetSnapshotAsync();

        var dictionary = snapshot.ToDictionary();

        foreach ( var (key, value) in dictionary )
        {
            Debug.Log( $"{key}: {value}" );
        }
    }
}

オフラインの状態でまだ端末キャッシュされていないデータを
DocumentReference.GetSnapshotAsync で取得しようとすると

FirestoreException: Failed to get document because the client is offline.

サーバーからデータを取得しようとして上記の例外が発生する

解決方法

using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Firebase.Firestore;
using Kogane;
using UnityEngine;

public class Example : MonoBehaviour
{
    private async UniTaskVoid Start()
    {
        // https://github.com/baba-s/Kogane.InternetCheckerInstance
        var instance = new InternetCheckerInstance
        (
            "8.8.8.8", // Google Public DNS
            "8.8.4.4"  // Google Public DNS
        );

        var firestore = FirebaseFirestore.DefaultInstance;

        var documentReference = firestore
                .Collection( "users" )
                .Document( "players" )
            ;

        // パブリック DNS に ping を実行することでオンライかどうかを確認
        var isOnline = await instance.IsOnlineAsync( 5 );

        // オンラインならサーバーからデータを取得、
        // オフラインなら端末のキャッシュからデータを取得することで
        // オフラインの時にサーバーにデータを取得しにいかないようにする
        var source = isOnline ? Source.Default : Source.Cache;

        // オフラインかつまだ端末にデータのキャッシュが存在しない場合は
        // try ~ catch で例外を握りつぶして初期値を使用
        var dictionary = new Dictionary<string, object>();

        try
        {
            var snapshot = await documentReference.GetSnapshotAsync( source );
            dictionary = snapshot.ToDictionary();
        }
        catch ( FirestoreException )
        {
        }

        foreach ( var (key, value) in dictionary )
        {
            Debug.Log( $"{key}: {value}" );
        }
    }
}

上記のようなコードにすることで
オフラインかつまだ端末にデータのキャッシュが存在しない場合でも
例外が発生せずにアプリが動作するようになる