【问题标题】:How to get the latest ID from Firebase console from Untiy如何从 Unity 的 Firebase 控制台获取最新 ID
【发布时间】:2020-02-19 18:43:09
【问题描述】:

我有一个使用 Firebase 进行 Google 身份验证的 Unity 项目。我将用户信息存储在实时数据库中。它们存储为:

UnityProject
    1->
       Name: "Something"
       Email: "Something"
    2->
       Name: "some other thing"
       Email: "Something else"

现在,这 1,2 将由我给出(用作主键)。我将从给第一个用户 ID 1 和第二个使用的 ID 2 开始,依此类推。

但我需要从 Firebase 取回存储的最后一个 ID。例如,

idToInsert = GetLastUsedID() + 1;

我已使用此代码,但它不起作用。屏幕会冻结,直到我强制关闭 Unity。

 public int GetLastUsedID()
    {
        int currentID = 1;
        bool continueSearch = true;

        while (continueSearch)
        {
            FirebaseREST.DatabaseReference reference = FirebaseREST.FirebaseDatabase.Instance.GetReference(""+currentID);
            string value = "";
            currentID++;
            reference.GetValueAsync(10, (res) =>
            {
                if (res.success)
                {
                    value = res.data.GetRawJsonValue();
                    Debug.Log("Success fetched data : " + value);
                    if(value == "")
                    {
                        continueSearch = false;
                        Debug.Log(currentID);
                    }
                }
                else
                {
                    Debug.Log("Fetch data failed : " + res.message);
                    continueSearch = false;
                }
            });

        }
        return currentID;
}

基本上,我只是想从 1 迭代直到我得到空字符串。空字符串表示该 ID 下不存在数据。

【问题讨论】:

  • 好好看看你的函数,尤其是while循环和.GetValueAsync,因为我不知道这是否是你想要实现的。 GetValueAsync 顾名思义,它的工作是异步的,第二个它被称为你的 while 循环的主体再次开始工作。我认为这不是你的意图,对吗?
  • 我只想获取数据库中的最后一个数字。在函数中获取 id1 的值。如果返回空字符串,则停止整个循环...

标签: c# firebase unity3d firebase-realtime-database


【解决方案1】:

我对@9​​87654328@ 不熟悉(如果可以的话,我建议使用official Firebase plugin,它不仅仅是调用 REST 端点),但我想我可以看到你的问题。

GetValueAsync 可能在后台异步运行。因此,块内的逻辑((res)=> 部分)多次触发(基本上是无限循环)。然后,根据这是如何实现的,continueSearch 永远不会转到 false,因为它没有标记为 volatile,或者回调逻辑永远不会有机会运行(例如,如果 FirebaseREST 尝试调度到主线程,它被锁定在一个无限的while循环中)。

如果GetValueAsync 返回一个任务,您可以使用我在this article 中介绍的一些技巧。我的建议是尝试使用 async/await,因此您的逻辑看起来更像:

async public int GetLastUsedID()
{
    volatile int currentID = 1;
    volatile bool continueSearch = true;

    while (continueSearch)
    {
        FirebaseREST.DatabaseReference reference = FirebaseREST.FirebaseDatabase.Instance.GetReference(""+currentID);
        string value = "";
        currentID++;
        await reference.GetValueAsync(10, (res) =>
        {
            if (res.success)
            {
                value = res.data.GetRawJsonValue();
                Debug.Log("Success fetched data : " + value);
                if(value == "")
                {
                    continueSearch = false;
                    Debug.Log(currentID);
                }
            }
            else
            {
                Debug.Log("Fetch data failed : " + res.message);
                continueSearch = false;
            }
        });
    }
    return currentID;
}

情况可能并非如此,在这种情况下,您可能希望将其转换为递归调用。您需要一些功能,例如:

public void GetLastUsedID(currentId)
{
        FirebaseREST.DatabaseReference reference = FirebaseREST.FirebaseDatabase.Instance.GetReference(""+currentID);
        reference.GetValueAsync(10, (res) =>
        {
            if (res.success)
            {
                value = res.data.GetRawJsonValue();
                Debug.Log("Success fetched data : " + value);
                if(value == "")
                {
                    continueSearch = false;
                    Debug.Log(currentID);
                }
                else
                {
                    // recurse
                    GetLastID(currentId+1);
                }
            }
            else
            {
                Debug.Log("Fetch data failed : " + res.message);
                continueSearch = false;
            }
        });
}

你必须弄清楚如何传入你自己的回调来冒泡这样的成功或失败(练习给读者)。

最后,我会对你所做的一切保持谨慎。如果您要对用户进行身份验证,我建议您使用直接与实时数据库相关联的Firebase Authentication。最多您只能在其中存储用户 ID,并使用 security rules 确保只有该用户可以写入它(例如)。通过使用 Firebase 身份验证来管理用户数据并将其绑定到 RTDB 规则,您可以避免同样的错误this author made

【讨论】:

  • 很好的答案。所以添加新用户需要主键权限。这就是为什么我只是依赖一个 ID 变量。有没有更好和/或正确的方法来做到这一点?
  • RTDB 中的主键概念并不完全符合您对 SQL 数据库的期望。您将需要某种类型的全局唯一密钥来识别您的条目,您可以使用 Firebase 身份验证中的用户 ID(您不想使用会话 ID 或其他任何真正应该是私有的)。如果您需要生成唯一键并且顺序无关紧要,您始终可以使用 Guid.NewGuid() 并将其缓存在您的 PlayerPrefs 中:docs.microsoft.com/en-us/dotnet/api/…
  • 这些也不必位于数据库的根目录。例如,您可以将它们全部嵌套在一个名为“users”的节点下,而不会影响性能。
  • 哦,好吧,所以我的 RTDB 应该看起来像 Unity Project -> Users -> 1,2,3...
  • 尽管我还没有尝试过解决方案,但我会将其标记为正确答案。我在唱官方 firebase 时遇到了一些问题,所以我选择了 FirebaseREST。我会用官方的火力基地做你所说的:)谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-19
  • 2019-04-10
相关资源
最近更新 更多