0
votes

Unity Script cesse de fonctionner lorsque vous essayez de changer de scène après avoir récupéré les données de Firebase

Ainsi, lorsque j'ai essayé d'obtenir des données de Firebase RealTime Database, les données ont été reçues avec succès. Mais quand j'ai essayé de changer de scène, le script a tout simplement cessé de fonctionner. Voici mon script complet:

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!!!");
          }
        });
    }
}

Quand je lance ce script, il y a juste show "Done!" connectez-vous à la console de journalisation. Le script de changement de scène et en dessous, par exemple, je veux écrire le journal "Terminé !!!" après le changement de scène, n'est pas exécuté.


0 commentaires

3 Réponses :


1
votes

pourquoi n'utilisez-vous pas DontDestroyOnLoad pour conserver les codes entre différentes scènes? Parce que le chargement d'une nouvelle scène détruit tous les objets Scene actuels. Dans ce cas, pourriez-vous essayer le code ci-dessous.

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!!!");
      }
    });
}
}


3 commentaires

Je comprends ce que tu veux dire, mais j'ai essayé ça, et je ne marcherai toujours pas. Scene2 n'est toujours pas chargé et Debug.Log ("Done !!!"); n'est toujours pas exécuté et je ne vois pas "Terminé !!!" à la console.


Ai-je raison? vous avez terminé toute votre tâche vous avez entré le bloc de code de else if (task.IsCompleted) {DataSnapshot snapshot = task.Result; // Faites quelque chose avec snapshot ... Debug.Log ("Done!"); SceneManager.LoadSceneAsync ("Scene2"); Debug.Log ("Terminé !!!"); } et cela ne fonctionnait toujours pas?


pouvez-vous également vérifier le nom de la scène comme "Scene2" et pouvez-vous également essayer d'utiliser loadscene au lieu de loadsceneAsync pour vous assurer que cela fonctionne



0
votes

La meilleure réponse est donc probablement d'essayer de mettre à jour la dernière version de le SDK Firebase . Le correctif spécifique qui, je pense, vous aidera est la version 6.5.0:

L'instance de FirebaseApp, FirebaseAuth, FirebaseDatabase, FirebaseFunctions, FirebaseInstanceId et FirebaseStorage sera maintenue active après sa création jusqu'à ce qu'elle soit explicitement supprimée.

Donc, comme mentionné ailleurs, vous devez probablement vous assurer que les scripts sont marqués comme DontDestroyOnLoad (gameObject); , en disant essentiellement à l'objet du jeu entier (en supposant qu'il se trouve à la racine de la scène) qu'il ne devrait pas ne disparaît pas quand sa scène parente change. Pour plus de détails et des mises en garde, consultez la documentation Unity .

Il y a également eu un changement dans le SDK Firebase qui, je pense, vous aidera. Chaque fois que vous appelez quelque chose comme FirebaseApp.DefaultInstance , Firebase effectue une certaine initialisation paresseuse sur cet objet. Comme dans, vérifiez d'abord si DefaultInstance est nul. Si tel est le cas, créez-le et renvoyez-le. Ceci est un modèle singleton typique.

Le changement est que, pour diverses raisons, c'était une référence faible. À partir de la version 6.5.0, cela a été transformé en une référence C # normale (ce qui signifie qu'il est beaucoup moins susceptible d'être nettoyé), ce qui peut éliminer de nombreux bogues autour de «la scène a changé et quelque chose a cessé de fonctionner».

À part cela, assurez-vous simplement d'utiliser DontDestroyOnLoad et assurez-vous qu'il fait ce que vous attendez (c'est-à-dire: appliquez-le à un objet de jeu à la racine de la scène plutôt qu'à un MonoBehaviour ou un objet enfant ).

--Patrick


0 commentaires

4
votes

Il s'agit d'un problème classique de continuation des tâches dans Unity à l'aide de Firebase. Lorsque vous utilisez, ContinueWith , il n'est pas garanti d'être appelé sur le thread Unity principal. Ce que vous essayez de faire SceneManager.LoadSceneAsync () nécessite d'être exécuté sur le thread principal Unity. Si vous essayez d'accéder à GameObjects dans ContinueWith , même cela échouera. Le code est juste fantôme sans aucune erreur dans la console.

La solution: Au lieu de ContinueWith , utilisez ContinueWithOnMainThread depuis Extensions Firebase qui ont été créées exactement pour cette raison.


2 commentaires

Votre réponse est vraiment comprendre mon problème et la solution. J'ai essayé cela et cela a fonctionné comme je l'espérais. Merci beaucoup.


Ce problème peut également être résolu en utilisant la méthode d'attente async et en stockant la tâche en tant que résultat dans une variable, une fois l'opération d'attente terminée, vérifiez le résultat de la tâche dans la condition et faites tout ce qui est nécessaire.