从Firebase获取数据后尝试更改场景时Unity脚本停止工作

时间:2019-09-16 09:47:02

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

因此,当我尝试从Firebase RealTime数据库获取数据时,数据被成功接收。但是,当我尝试更改场景时,脚本只是停止工作。这是我的完整脚本:

using Firebase;
using Firebase.Database;
using Firebase.Extensions;
using Firebase.Unity.Editor;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class NewBehaviourScript : MonoBehaviour
{
    DependencyStatus dependencyStatus = DependencyStatus.UnavailableOther;
    protected bool isFirebaseInitialized = false;
    // Start is called before the first frame update
    private void Start()
    {

        FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task => {
            dependencyStatus = task.Result;
            if (dependencyStatus == DependencyStatus.Available)
            {
                InitializeFirebase();
            }
            else
            {
                Debug.LogError(
                  "Could not resolve all Firebase dependencies: " + dependencyStatus);
            }
        });
    }
    protected virtual void InitializeFirebase()
    {
        FirebaseApp app = FirebaseApp.DefaultInstance;
        // NOTE: You'll need to replace this url with your Firebase App's database
        // path in order for the database connection to work correctly in editor.
        app.SetEditorDatabaseUrl("https://frim-exam.firebaseio.com/");
        if (app.Options.DatabaseUrl != null)
            app.SetEditorDatabaseUrl(app.Options.DatabaseUrl);
        StartListener();
        isFirebaseInitialized = true;
    }

    void StartListener()
    {
        FirebaseDatabase.DefaultInstance
      .GetReference("Leaders")
      .GetValueAsync().ContinueWith(task => {
            if (task.IsFaulted)
            {
                // Handle the error...
            }
            else if (task.IsCompleted)
            {
                DataSnapshot snapshot = task.Result;
              // Do something with snapshot...
              Debug.Log("Done!");
              SceneManager.LoadSceneAsync("Scene2");
              Debug.Log("Done!!!");
          }
        });
    }
}

当我运行此脚本时,仅显示“完成!”。在日志控制台上登录。更改场景脚本及其下的脚本,例如,我想写日志“ Done !!!”(完成!!!)场景更改后,不执行。

3 个答案:

答案 0 :(得分:1)

为什么不使用DontDestroyOnLoad在不同场景之间保留代码?因为新场景的加载会破坏所有当前的场景对象。对于这种情况,您可以尝试以下代码吗?

using Firebase;
using Firebase.Database;
using Firebase.Extensions;
using Firebase.Unity.Editor;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;


private static bool created = false;

// the belowing code is used for changing the scene without losing the script
    void Awake()
    {
        if (!created)
        {
            DontDestroyOnLoad(this.gameObject);
            created = true;
            Debug.Log("Awake: " + this.gameObject);
        }
    }

public class NewBehaviourScript : MonoBehaviour
{
DependencyStatus dependencyStatus = DependencyStatus.UnavailableOther;
protected bool isFirebaseInitialized = false;
// Start is called before the first frame update
private void Start()
{

    FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task => {
        dependencyStatus = task.Result;
        if (dependencyStatus == DependencyStatus.Available)
        {
            InitializeFirebase();
        }
        else
        {
            Debug.LogError(
              "Could not resolve all Firebase dependencies: " + dependencyStatus);
        }
    });
}
protected virtual void InitializeFirebase()
{
    FirebaseApp app = FirebaseApp.DefaultInstance;
    // NOTE: You'll need to replace this url with your Firebase App's database
    // path in order for the database connection to work correctly in editor.
    app.SetEditorDatabaseUrl("https://frim-exam.firebaseio.com/");
    if (app.Options.DatabaseUrl != null)
        app.SetEditorDatabaseUrl(app.Options.DatabaseUrl);
    StartListener();
    isFirebaseInitialized = true;
}

void StartListener()
{
    FirebaseDatabase.DefaultInstance
  .GetReference("Leaders")
  .GetValueAsync().ContinueWith(task => {
        if (task.IsFaulted)
        {
            // Handle the error...
        }
        else if (task.IsCompleted)
        {
            DataSnapshot snapshot = task.Result;
          // Do something with snapshot...
          Debug.Log("Done!");
          SceneManager.LoadSceneAsync("Scene2");
          Debug.Log("Done!!!");
      }
    });
}
}

答案 1 :(得分:1)

这是Unity中使用Firebase的经典任务延续问题。使用ContinueWith时,不能确保在Unity主线程上调用它。您要SceneManager.LoadSceneAsync()进行的操作需要在Unity主线程上执行。如果您尝试访问ContinueWith内部的GameObjects,那么即使那样也会失败。代码只是隐藏了出来,在控制台中没有任何错误。

解决方案: 正是出于这个原因而使用ContinueWithOnMainThread中的Firebase extensions,而不是ContinueWith

答案 2 :(得分:0)

因此,最好的答案可能就是尝试更新为latest version of the firebase SDK。我想为您提供帮助的特定修补程序是6.5.0:

  

FirebaseApp,FirebaseAuth,FirebaseDatabase,FirebaseFunctions,FirebaseInstanceId和FirebaseStorage的实例在创建后将一直保持活动状态,直到明确处置为止。

因此,就像在其他地方提到的那样,您可能只需要确保将脚本标记为DontDestroyOnLoad(gameObject);,就可以基本告诉整个游戏对象(假设它位于场景的根),当它的父对象不消失时,场景变化。有关详细信息和注意事项,请参见Unity documentation

我认为Firebase SDK也有所更改,可以为您提供帮助。每当您调用类似FirebaseApp.DefaultInstance之类的内容时,Firebase都会对该对象进行一些延迟的初始化。与之类似,首先检查DefaultInstance是否为空。如果是这样,请创建它并将其退回。这是典型的单例模式。

更改是出于各种原因,这曾经是一个较弱的参考。从6.5.0版开始,它已成为普通的C#参考(这意味着它被清理的可能性要小得多),可以摆脱“场景改变,某些东西停止工作”周围的许多错误。

除此以外,只需确保使用DontDestroyOnLoad并确保它正在执行您期望的操作(即:将其应用于场景根源的游戏对象,而不是MonoBehaviour或子对象)。 / p>

-帕特里克