首页 > 解决方案 > 如何从 Unity 中的 firebase 读取值?

问题描述

我真的不明白如何从 firebase 读取任何值。在谷歌文档中,据说我需要使用 GetValueAsync().ContinueWith(),但它的工作原理相当奇怪。所以,如果我使用:

FirebaseDatabase.DefaultInstance.GetReference("Leaders").GetValueAsync().ContinueWith(task => {
    if (task.IsFaulted) {
      Debug.Log("error");
    }
    else if (task.IsCompleted) {
      DataSnapshot snapshot = task.Result;
      Debug.Log(snapshot.Value.ToString());
    }
  });

然后它打印真实值,一切正常。但是,如果我试图找到具有此名称的 GameObject,则不会发生任何事情。

else if (task.IsCompleted) {
  DataSnapshot snapshot = task.Result;
  Debug.Log(GameObject.Find(snapshot.Value.ToString()).name);
} 

它不打印任何东西。它停在这条线上,但没有任何错误或消息。每次我尝试使用快照时都会发生这个问题。一个非常简单的事情,但我无法想象有什么问题?请帮忙。

标签: c#firebaseunity3dfirebase-realtime-database

解决方案


写了一篇文章录制了一个关于在 Unity 中处理多任务的视频,如果你对所有选项感到好奇,你一定要看看这些。

具体针对您的问题,我建议只需更改ContinueWithContinueWithOnMainThread. 这是替代品的下降。

FirebaseDatabase.DefaultInstance.GetReference("Leaders").GetValueAsync().ContinueWithOnMainThread(task => {
    if (task.IsFaulted) {
      Debug.Log("error");
    }
    else if (task.IsCompleted) {
      DataSnapshot snapshot = task.Result;
      Debug.Log(snapshot.Value.ToString());
    }
  });

这让我解释了正在发生的事情:

Firebase 和 Unity 的棘手之处在于 Firebase 倾向于在后台线程上执行工作,以避免因长时间运行的网络操作而阻塞您的游戏。与Unity 的 UnityWebRequest等 API 不同,开发人员可以自行决定如何以及何时将逻辑移回游戏线程。这意味着如果您想在后台使用此操作的结果做更多​​的工作,您可以,但这也意味着如果您开始在延续中执行非线程安全操作,您将面临非常意外的行为。

Unity 保护某些功能,例如GameObject.Find,在后台线程中的访问——当它检测到不愉快的事情时,通常会引发异常。ContinueWith将在长时间运行的任务完成的任何地方开始执行,而ContinueWithOnMainThread将您的延续逻辑推送到在主线程上执行的队列中。这通常是有效的,并且将确保您在延续中执行的任何 Unity 逻辑都在预期的时间发生。

您可以选择通过编写以下方式将任务转换为协程:

var task = FirebaseDatabase.DefaultInstance.GetReference("Leaders").GetValueAsync();
yield return new WaitUntil(()=>task.IsComplete);
if (task.Exception) {
    // something bad happened, handle it
    yield break;
}
var snapshot = task.Result;

这将使您能够更好地控制逻辑在游戏中的执行位置,并提供更多的内存安全性。您还可以使用 async/await 使代码看起来更像典型的 C#。


推荐阅读