处理Firebase的“任务"并在Unity中实施Manager类(适用于Firebase) [英] Handling Firebase "Tasks" and implement Manager Classes (for Firebase) in Unity

查看:85
本文介绍了处理Firebase的“任务"并在Unity中实施Manager类(适用于Firebase)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为服务器端完全基于Firebase的游戏编写代码.我希望在游戏中使用Auth,数据库,InstanceID,消息传递和云函数.作为C#的新手,我第一次在Firebase中遇到了C#任务".我将使用数据库很多次(例如分数更新",朋友请求",聊天",朋友做到了",朋友做到了").我对Singleton Pattern(GameManagers,EnemyManagers,SoundManagers等)感到很满意.但是使用Firebase,因为它的大多数调用都是异步的,并且是通过Tasks实现的.我认为我需要采取不同的解决方法来实施Manager.

I'm writing the code for a game whose server-side is totally based on Firebase. I expect to use Auth, Database, InstanceID, Messaging and Cloud Functions in the game. Being a novice C# Programmer, I encountered with C# "Tasks" first time with Firebase. I'm going to use Database for a lot of times (like Score Update, Friends Requests, Chat, Friend Did this, Friend Did that). I mostly feel comfortable with Singleton Pattern (GameManagers, EnemyManagers, SoundManagers etc..). But with Firebase, since most of its calls are asynchronous and implemented via Tasks. I think I need to workaround differently to implement Managers.

例如,我需要向特定朋友发送朋友请求".UIManager是处理UI事件等的脚本.我想从此脚本调用Method到另一个Manager(例如,FriendsManager).但是我需要首先检查这个朋友是否已经是Database的我的朋友?所以,我要做的是

For example, I need to send a Friend Request to a specific friend. The UIManager is a script that deals with UI events etc. I'd like to call Method from this script to another Manager (say FriendsManager). But I need to first check if this friend is already friend of mine from Database or Not? So, what I would do is

class UIManager
{
   void OnFriendRequestClicked(string friendId)
   {
      bool userExists = FriendsManager.instance.UserExists(friendId);
      if(userExists)
            // Proceed with Sending Request
               FriendsManager.instance.SendRequest(friendId);
       else 
          // Show a Dialogue that User ID is invalid
          ShowError("User Id is invalid");

       // NOTE: The above code block of "condition" is executed before 
       // the UserID is validated from FriendsManager
       // I know its because of Task. But how can I alter this code 
       // to do something in the similar pattern? 
   }
}

class FriendsManager
{
   bool UserExists(string userIdToCheck)
   {
    reference.Child("users").Child(userIdToCheck).GetValueAsync().ContinueWith(
  task=>
   {
       if(task.IsCompleted)
         {
             if(task.Result == null)
                  return false;    // (expected) Return false to Method "UserExists"
             else 
                  return true;    //(expected) Return true to Method "UserExists" 

       // But this won't actually return "bool" to the method,
      // it actually returns to its own "Task"
     //NOTE: -> How to Return from here to the Method? 
   )};   
}

推荐答案

数据是从Firebase异步加载的.该应用程序继续运行,而不是在加载数据时等待/阻止.然后,当数据可用时,它将调用您的回调.

Data is loaded from Firebase asynchronously. Instead of waiting/blocking while the data is being loaded, the app continues. And then when the data is available, it calls your callback.

通过一些日志记录语句,您可以最轻松地看到这一点:

You can most easily see this with some logging statements:

Debug.Log("Before starting to load data");

reference.Child("users").Child(userIdToCheck).GetValueAsync().ContinueWith(task=> {
   Debug.Log("Data loaded");
});

Debug.Log("After starting to load data");

运行此代码时,它将记录:

When you run this code it logs:

开始加载数据之前

Before starting to load data

开始加载数据后

已加载数据

这可能不是您所期望的,但是可以完美地解释为什么您不能从回调中返回值: UserExists 到那时已经完成了.

That is probably not what you expected, but explains perfectly why you can't return a value from within the callback: the UserExists has already finished at that point.

这意味着任何需要访问数据库数据的代码都必须在 ContinueWith 块的内部 (或从那里调用).

This means that any code that needs access to the data from the database, must be inside the ContinueWith block (or be called from there).

最简单的方法是将代码从您的 OnFriendRequestClicked 移到 UserExists :

The simplest approach is to move the code from your OnFriendRequestClicked into UserExists:

bool UserExists(string userIdToCheck) {
  reference.Child("users").Child(userIdToCheck).GetValueAsync().ContinueWith(task=>
{
   if(task.IsCompleted)
   {
       if(task.Result == null)
           ShowError("User Id is invalid");
       else 
           FriendsManager.instance.SendRequest(friendId);
   )};   
}

然后可以在不带 if 的情况下调用此函数.

You can then call this function without the if after it.

上述方法效果很好,但是这意味着您的 UserExists 方法在不同情况下不再可重用.要使其可重复使用,可以将自己的回调接口传递给 UserExists .

The above approach works great, but means that your UserExists method is no longer reusable in different cases. To make it reusable again, you can pass your own callback interface into UserExists.

例如,使用 Task :

bool UserExists(string userIdToCheck, Action<bool> callback) {
  reference.Child("users").Child(userIdToCheck).GetValueAsync().ContinueWith(task=>
{
   if(task.IsCompleted)
   {
       if(task.Result == null)
           callback(false);
       else 
           callback(true);
   )};   
}

然后调用它:

FriendsManager.instance.UserExists(friendId, userExists => {
    if(userExists)
        FriendsManager.instance.SendRequest(friendId);
    else 
        ShowError("User Id is invalid");
})

这篇关于处理Firebase的“任务"并在Unity中实施Manager类(适用于Firebase)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆