簡體   English   中英

Cloud Firestore GetSnapshotAsync 以返回一個值。 統一與C#

[英]Cloud Firestore GetSnapshotAsync to return a value. Unity and C#

我正在嘗試創建一個 Class 來管理我的 Cloud Firestore 請求(就像任何 SQLiteHelper 類一樣)。 但是,firebase 使用異步調用,我無法將值返回給其他腳本。 這里是一個例子(布爾返回):

    public bool CheckIfIsFullyRegistered(string idUtente)
    {
        DocumentReference docRef = db.Collection("Utenti").Document(idUtente);
        docRef.GetSnapshotAsync().ContinueWithOnMainThread(task =>
        {
            DocumentSnapshot snapshot = task.Result;
            if (snapshot.Exists)
            {                
                Debug.Log(String.Format("Document {0} exist!", snapshot.Id));
                return true; //Error here
            }
            else
            {
                Debug.Log(String.Format("Document {0} does not exist!", snapshot.Id));
            }
        });
    }

不幸的是,由於 Firestore 充當一些運行緩慢的 I/O(磁盤訪問或 web 請求)的前端,因此您與之進行的任何交互都需要是異步的。 在執行此訪問時,您還需要盡可能避免阻塞您的游戲循環。 也就是說,不會有對GetSnapshotAsync的同步調用。

現在,您有兩種選擇可以編寫感覺同步的代碼(如果您像我一樣,這樣思考比使用回調或反應結構更容易)。

首先是GetSnapshotAsync返回一個任務。 您可以選擇在async function 中await該任務:

public async bool CheckIfIsFullyRegistered(string idUtente)
{
    DocumentReference docRef = db.Collection("Utenti").Document(idUtente);

    // this is equivalent to `task.Result` in the continuation code
    DocumentSnapshot snapshot = await docRef.GetSnapshotAsync()
    return snapshot.Exists;
}

問題在於async / await對 C# object 生命周期做出了一些假設,這些假設在 Unity 上下文中無法保證(更多信息在我的相關博客文章視頻中)。 如果您是一名長期的 Unity 開發人員,或者只是想避免this == null永遠為真,您可以選擇將異步調用包裝在WaitUntil塊中:

private IEnumerator CheckIfIsFullyRegisteredInCoroutine() {
    string idUtente;

    // set idUtente somewhere here

    var isFullyRegisteredTask = CheckIfIsFullyRegistered(idUtente);
    yield return new WaitUntil(()=>isFullyRegisteredTask.IsComplete);
    
    if (isFullyRegisteredTask.Exception != null) {
        // do something with the exception here
        yield break;
    }

    bool isFullyRegistered = isFullyRegisteredTask.Result;
}

我喜歡采用的另一種模式是使用偵聽器,而不僅僅是檢索快照。 我將使用來自 Firestore(或 RTDB)的任何最新數據填充一些 Unity 端 class,並讓我的所有 Unity 對象 ping MonoBehaviour。 這特別適合Unity 的新 ECS 架構或您在每幀基礎上查詢數據的任何時候。

希望對大家有幫助!

這就是我讓它工作的方式,但請原諒我的無知,因為我只使用了一周左右的 FBDB。

這是一個片段,我希望它對某人有所幫助。

為我們的登錄事件創建一個線程任務擴展

    static Task DI = new System.Threading.Tasks.Task(LoginAnon);

匿名登錄

DI = FirebaseAuth.DefaultInstance.SignInAnonymouslyAsync().ContinueWith(result =>
    {
        Debug.Log("LOGIN [ID: " + result.Result.UserId + "]");
        userID = result.Result.UserId;
        FirebaseDatabase.DefaultInstance.GetReference("GlobalMsgs/").ChildAdded += HandleNewsAdded;
        FirebaseDatabase.DefaultInstance.GetReference("Users/" + userID + "/infodata/nickname/").ValueChanged += HandleNameChanged;
        FirebaseDatabase.DefaultInstance.GetReference("Users/" + userID + "/staticdata/status/").ValueChanged += HandleStatusChanged;
        FirebaseDatabase.DefaultInstance.GetReference("Lobbies/").ChildAdded += HandleLobbyAdded;
        FirebaseDatabase.DefaultInstance.GetReference("Lobbies/").ChildRemoved += HandleLobbyRemoved;
        loggedIn = true;
    });

然后獲取值。

            DI.ContinueWith(Task =>
        {
            FirebaseDatabase.DefaultInstance.GetReference("Lobbies/" + selectedLobbyID + "/players/").GetValueAsync().ContinueWith((result) =>
            {
                DataSnapshot snap2 = result.Result;
                Debug.Log("Their nickname is! -> " + snap2.Child("nickname").Value.ToString());
                Debug.Log("Their uID is! -> " + snap2.Key.ToString());

                //Add the user ID to the lobby list we have
                foreach (List<string> lobbyData in onlineLobbies)
                {
                    Debug.Log("Searching for lobby:" + lobbyData[0]);
                    if (selectedLobbyID == lobbyData[0].ToString()) //This is the id of the user hosting the lobby
                    {
                        Debug.Log("FOUND HOSTS LOBBY ->" + lobbyData[0]);
                        foreach (DataSnapshot snap3 in snap2.Children)
                        {
                            //add the user key to the lobby
                            lobbyData.Add(snap3.Key.ToString());
                            Debug.Log("Added " + snap3.Child("nickname").Value.ToString() + " with ID: " + snap3.Key.ToString() + " to local lobby.");
                            currentUsers++;
                        }
                        return;
                    }
                }
            });
        });

顯然,您可以根據自己的喜好對其進行更改,它實際上並不需要循環,但我正在使用它們進行測試,然后再將代碼壓縮為可讀性較差且更直觀的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM