Cloud Firestore GetSnapshotAsync返回一个值。统一与C#

Cloud Firestore GetSnapshotAsync返回一个值。统一与C#,c#,firebase,unity3d,asynchronous,C#,Firebase,Unity3d,Asynchronous,我正试图创建一个类来管理我的CloudFireStore请求(就像任何SQLiteHelper类一样)。但是,firebase使用异步调用,我无法向其他脚本返回值。 下面是一个示例(bool return): 不幸的是,由于Firestore充当一些运行缓慢的I/O(磁盘访问或web请求)的前端,因此您与它的任何交互都需要是异步的。在执行此访问时,如果可能的话,您还希望避免阻塞游戏循环。也就是说,不会有对GetSnapshotAsync的同步调用 现在有两种方法可以用来编写感觉同步的代码(如果你

我正试图创建一个类来管理我的CloudFireStore请求(就像任何SQLiteHelper类一样)。但是,firebase使用异步调用,我无法向其他脚本返回值。 下面是一个示例(bool return):


不幸的是,由于Firestore充当一些运行缓慢的I/O(磁盘访问或web请求)的前端,因此您与它的任何交互都需要是异步的。在执行此访问时,如果可能的话,您还希望避免阻塞游戏循环。也就是说,不会有对
GetSnapshotAsync
的同步调用

现在有两种方法可以用来编写感觉同步的代码(如果你像我一样,这样想比回调或反应式结构更容易)

首先是
GetSnapshotAsync
返回一个任务。您可以在
async
功能中选择等待该任务的
wait

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 lifecycle做了一些假设,而这些假设在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端类,并让我的所有Unity对象ping该行为。这特别适合于在每帧的基础上查询数据的任何时候


我希望一切都有帮助

这就是我使用FBDB的方法,但请原谅我的无知,因为我使用FBDB才一周左右

这里是一个片段,我希望它能帮助一些人

创建登录事件的线程任务扩展

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

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;
                    }
                }
            });
        });
DI.ContinueWith(任务=>
{
FirebaseDatabase.DefaultInstance.GetReference(“Lobbies/”+selectedLobbyID+“/players/”).GetValueAsync().ContinueWith((结果)=>
{
DataSnapshot snap2=result.result;
Log(“他们的昵称是!->”+snap2.Child(“昵称”).Value.ToString());
Log(“他们的uID是!->”+snap2.Key.ToString());
//将用户ID添加到我们拥有的大厅列表中
foreach(在OnlineObjes中列出游说数据)
{
Log(“搜索大厅:+lobbyData[0]);
if(selectedLobbyID==lobbyData[0].ToString())//这是承载大厅的用户的id
{
Log(“找到主机游说->”+游说数据[0]);
foreach(snap2.Children中的DataSnapshot snap3)
{
//将用户密钥添加到大厅
添加(snap3.Key.ToString());
Debug.Log(“将ID为“+snap3.Key.ToString()+”的“+snap3.Child(“昵称”).Value.ToString()+”添加到本地大厅”);
当前用户++;
}
返回;
}
}
});
});

显然,您可以随意更改它,它实际上不需要循环,但我正在使用它们进行测试,然后再将代码压缩为可读性较差、更直观的内容。

这正是我要搜索的内容。非常感谢帕特里克!(我们是你在youtube和firebase上的忠实粉丝!)太棒了!我喜欢做这些,所以听说它们很有用真是太好了。
            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;
                    }
                }
            });
        });