Firebase Database problem

Hello,
So I have a game with the mainMenu scene and Play scene. After I log in with LoginButton() the Text: usernameText is not updating, when I’m changing to Play scene and come back to mainMenu it is updating. displayScores is updating only after I log in again with LoginButton(). So to see the refreshed result table I have to click the LoginButton() again even though I am logged in. And after restarting the application in the editor, I see in the logs that I am logged in correctly, but the usernameText does not match the username again.
Everything is updating correctly on the server-side.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Firebase;
using Firebase.Auth;
using TMPro;
using System;
using Firebase.Database;
using Firebase.Unity.Editor;
using JetBrains.Annotations;
using UnityEngine.UI;



public class AuthManager : MonoBehaviour
{
    //Firebase variables
    [Header("Firebase")]
    public DependencyStatus dependencyStatus;
    public FirebaseAuth auth;
    public FirebaseUser User;

    //Login variables
    [Header("Login")]
    public TMP_InputField emailLoginField;
    public TMP_InputField passwordLoginField;
    public TMP_Text warningLoginText;
    public TMP_Text confirmLoginText;

    //Register variables
    [Header("Register")]
    public TMP_InputField usernameRegisterField;
    public TMP_InputField emailRegisterField;
    public TMP_InputField passwordRegisterField;
    public TMP_InputField passwordRegisterVerifyField;
    public TMP_Text warningRegisterText;

    public string userName;
    public Text usernameText;

    ArrayList leaderBoard;
    public Text displayScores;
    private bool addScorePressed;
    private const int MaxScores = 5;
    private int score = 100;


    private string DATA_URL = "https://test-game.firebaseio.com/";

    private DatabaseReference databaseReference;
    //private DependencyStatus dependencyStatus;

    void Awake()
    {
        //Check that all of the necessary dependencies for Firebase are present on the system
        FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
        {
            dependencyStatus = task.Result;
            if (dependencyStatus == DependencyStatus.Available)
            {
                //If they are avalible Initialize Firebase
                InitializeFirebase();
            }
            else
            {
                Debug.LogError("Could not resolve all Firebase dependencies: " + dependencyStatus);
            }
        });
    }

    private void Start()
    {
        addScorePressed = true;
        leaderBoard = new ArrayList();
        leaderBoard.Add("Top " + MaxScores.ToString() + " Scores");

        Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
        {
            dependencyStatus = task.Result;
            if (dependencyStatus == DependencyStatus.Available)
            {
                InitializeFirebase();
            }
            else
            {
                Debug.LogError("Could not resolve all Firebase dependencies: " + dependencyStatus);
            }
        });
    }


    //protected void InitializeFirebaseData()
    //{
    //    FirebaseApp.DefaultInstance.SetEditorDatabaseUrl(DATA_URL);
    //    databaseReference = FirebaseDatabase.DefaultInstance.RootReference;
    //    StartListener();       
    //}

    //private void InitializeFirebase()
    //{
    //    //Set the authentication instance object
    //    auth = FirebaseAuth.DefaultInstance;
    //    //Debug.Log("Setting up Firebase Auth");
    //    UpdateInitialize();
    //}

    private void InitializeFirebase()
    {
        auth = FirebaseAuth.DefaultInstance;

        FirebaseApp.DefaultInstance.SetEditorDatabaseUrl(DATA_URL);
        databaseReference = FirebaseDatabase.DefaultInstance.RootReference;
        StartListener();

        UpdateInitialize();
    }

    public void UpdateInitialize()
    {
        if (auth.CurrentUser != null)
        {
            var user = auth.CurrentUser;
            Debug.LogFormat("User signed in succesfully: {0} ({1})", user.DisplayName, user.Email);
            userName = user.DisplayName;
            usernameText.text = user.DisplayName;
        }
    }

    public void writeNewUser(string email, string name, string pass, int score)
    {
        Player user = new Player( emailRegisterField.text, usernameRegisterField.text, passwordRegisterField.text, PlayerPrefs.GetInt("HighScore"));
        string json = JsonUtility.ToJson(user);
        databaseReference.Child("users").Push().SetRawJsonValueAsync(json);
    }


    public void WriteNewScore(string userId, int score)
    {
        // Create new entry at /user-scores/$userid/$scoreid and at
        // /leaderboard/$scoreid simultaneously
        string key = databaseReference.Child(userId)/*.Push()*/.Key;
        LeaderboardEntry entry = new LeaderboardEntry(userId, score);
        Dictionary<string, object> entryValues = entry.ToDictionary();

        Dictionary<string, object> childUpdates = new Dictionary<string, object>();
        //childUpdates["/scores/" + key] = entryValues;
        childUpdates["/Highscore/" /*+ userId*/ + "/" + key] = entryValues;

        databaseReference.UpdateChildrenAsync(childUpdates);
    }

    protected void StartListener()
    {
        FirebaseDatabase.DefaultInstance
          .GetReference("Highscore").OrderByChild("score")
          .ValueChanged += (object sender2, ValueChangedEventArgs e2) => {
              if (e2.DatabaseError != null)
              {
                  Debug.LogError(e2.DatabaseError.Message);
                  return;
              }
              //Debug.Log("Received values for Leaders.");
              string title = leaderBoard[0].ToString();
              leaderBoard.Clear();
              leaderBoard.Add(title);
              if (e2.Snapshot != null && e2.Snapshot.ChildrenCount > 0)
              {
                  foreach (var childSnapshot in e2.Snapshot.Children)
                  {
                      if (childSnapshot.Child("score") == null
                    || childSnapshot.Child("score").Value == null)
                      {
                          Debug.LogError("Bad data in sample.  Did you forget to call SetEditorDatabaseUrl with your project id?");
                          break;
                      }
                      else
                      {
                        //  Debug.Log("Leaders entry : " +
                        //childSnapshot.Child("uid").Value.ToString() + " - " +
                        //childSnapshot.Child("score").Value.ToString());
                          leaderBoard.Insert(1, childSnapshot.Child("score").Value.ToString()
                        + " . . . . . . " + childSnapshot.Child("uid").Value.ToString());

                          displayScores.text = "";
                          foreach (string item in leaderBoard)
                          {
                              displayScores.text += "\n" + item;
                          }
                      }
                  }
              }
          };
    }
    // DataBase^


    //Function for the login button
    public void LoginButton()
    {
        //Call the login coroutine passing the email and password
        StartCoroutine(Login(emailLoginField.text, passwordLoginField.text));
    }

    public void AutoLoginButton()
    {
        StartCoroutine(AutoLogin(PlayerPrefs.GetString("userEmail"), PlayerPrefs.GetString("userPassword")));
    }
    //Function for the register button
    public void RegisterButton()
    {
        //Call the register coroutine passing the email, password, and username
        StartCoroutine(Register(emailRegisterField.text, passwordRegisterField.text, usernameRegisterField.text));
    }

    public void SingOutButton()
    {
        auth.SignOut();
    }

    private IEnumerator Login(string _email, string _password)
    {
        //Call the Firebase auth signin function passing the email and password
        var LoginTask = auth.SignInWithEmailAndPasswordAsync(_email, _password);
        //Wait until the task completes
        yield return new WaitUntil(predicate: () => LoginTask.IsCompleted);

        if (LoginTask.Exception != null)
        {
            //If there are errors handle them
            Debug.LogWarning(message: $"Failed to register task with {LoginTask.Exception}");
            FirebaseException firebaseEx = LoginTask.Exception.GetBaseException() as FirebaseException;
            AuthError errorCode = (AuthError)firebaseEx.ErrorCode;

            string message = "Login Failed!";
            switch (errorCode)
            {
                case AuthError.MissingEmail:
                    message = "Missing Email";
                    break;
                case AuthError.MissingPassword:
                    message = "Missing Password";
                    break;
                case AuthError.WrongPassword:
                    message = "Wrong Password";
                    break;
                case AuthError.InvalidEmail:
                    message = "Invalid Email";
                    break;
                case AuthError.UserNotFound:
                    message = "Account does not exist";
                    break;
            }
            warningLoginText.text = message;
        }
        else
        {
            //User is now logged in
            //Now get the result           
            User = LoginTask.Result;
            Debug.LogFormat("User signed in successfully: {0} ({1})", User.DisplayName, User.Email);
            warningLoginText.text = "";
            confirmLoginText.text = "Logged In";
           
            WriteNewScore(User.DisplayName, PlayerPrefs.GetInt("HighScore"));
            string name = User.DisplayName;           

            // Database
            DatabaseReference reference = FirebaseDatabase.DefaultInstance.GetReference("Highscore");

            reference.RunTransaction(AddScoreTransaction)
                 .ContinueWith(task => {
                 if (task.Exception != null)
                 {
                     Debug.Log(task.Exception.ToString());
                 }
                 else if (task.IsCompleted)
                 {
                     Debug.Log("Transaction complete.");
                 }
             });
            //update UI
            addScorePressed = true;
            usernameText.text = name.ToString();
        }
    }

    private IEnumerator Register(string _email, string _password, string _username)
    {
        if (_username == "")
        {
            //If the username field is blank show a warning
            warningRegisterText.text = "Missing Username";
        }
        else if (passwordRegisterField.text != passwordRegisterVerifyField.text)
        {
            //If the password does not match show a warning
            warningRegisterText.text = "Password Does Not Match!";
        }
        else
        {
            //Call the Firebase auth signin function passing the email and password
            var RegisterTask = auth.CreateUserWithEmailAndPasswordAsync(_email, _password);
            //Wait until the task completes
            yield return new WaitUntil(predicate: () => RegisterTask.IsCompleted);

            if (RegisterTask.Exception != null)
            {
                //If there are errors handle them
                Debug.LogWarning(message: $"Failed to register task with {RegisterTask.Exception}");
                FirebaseException firebaseEx = RegisterTask.Exception.GetBaseException() as FirebaseException;
                AuthError errorCode = (AuthError)firebaseEx.ErrorCode;

                string message = "Register Failed!";
                switch (errorCode)
                {
                    case AuthError.MissingEmail:
                        message = "Missing Email";
                        break;
                    case AuthError.MissingPassword:
                        message = "Missing Password";
                        break;
                    case AuthError.WeakPassword:
                        message = "Weak Password";
                        break;
                    case AuthError.EmailAlreadyInUse:
                        message = "Email Already In Use";
                        break;
                }
                warningRegisterText.text = message;
            }
            else
            {
                //User has now been created
                //Now get the result

                writeNewUser(emailRegisterField.text, usernameRegisterField.text, passwordRegisterField.text, PlayerPrefs.GetInt("HighScore"));
               

                User = RegisterTask.Result;

                if (User != null)
                {
                    //Create a user profile and set the username
                    UserProfile profile = new UserProfile { DisplayName = _username };

                    //Call the Firebase auth update user profile function passing the profile with the username
                    var ProfileTask = User.UpdateUserProfileAsync(profile);
                    //Wait until the task completes
                    yield return new WaitUntil(predicate: () => ProfileTask.IsCompleted);

                    if (ProfileTask.Exception != null)
                    {
                        //If there are errors handle them
                        Debug.LogWarning(message: $"Failed to register task with {ProfileTask.Exception}");
                        FirebaseException firebaseEx = ProfileTask.Exception.GetBaseException() as FirebaseException;
                        AuthError errorCode = (AuthError)firebaseEx.ErrorCode;
                        warningRegisterText.text = "Username Set Failed!";
                    }
                    else
                    {
                        //Username is now set
                        //Now return to login screen

                        PlayerPrefs.SetString("userEmail", emailRegisterField.text);
                        PlayerPrefs.SetString("userPassword", emailRegisterField.text);                                           
                        warningRegisterText.text = "";
                        StartCoroutine(AutoLogin(PlayerPrefs.GetString("userEmail"), PlayerPrefs.GetString("userPassword")));
                        LoginUIManager.instance.BackToMenu();
                    }
                }
            }
        }
    }

    private IEnumerator AutoLogin(string _email, string _password)
    {
        //Call the Firebase auth signin function passing the email and password
        var LoginTask = auth.SignInWithEmailAndPasswordAsync(PlayerPrefs.GetString("userEmail"), PlayerPrefs.GetString("userPassword"));
        //Wait until the task completes
        yield return new WaitUntil(predicate: () => LoginTask.IsCompleted);

        //if (LoginTask.Exception != null)
        //{
        //    //If there are errors handle them
        //    Debug.LogWarning(message: $"Failed to register task with {LoginTask.Exception}");
        //    FirebaseException firebaseEx = LoginTask.Exception.GetBaseException() as FirebaseException;
        //    AuthError errorCode = (AuthError)firebaseEx.ErrorCode;

        //    string message = "Login Failed!";
        //    switch (errorCode)
        //    {
        //        case AuthError.MissingEmail:
        //            message = "Missing Email";
        //            break;
        //        case AuthError.MissingPassword:
        //            message = "Missing Password";
        //            break;
        //        case AuthError.WrongPassword:
        //            message = "Wrong Password";
        //            break;
        //        case AuthError.InvalidEmail:
        //            message = "Invalid Email";
        //            break;
        //        case AuthError.UserNotFound:
        //            message = "Account does not exist";
        //            break;
        //    }
        //    warningLoginText.text = message;
        //}
        //else
        //{
            //User is now logged in
            //Now get the result           
            User = LoginTask.Result;
            Debug.LogFormat("User signed in successfully: {0} ({1})", User.DisplayName, User.Email);
            warningLoginText.text = "";
            confirmLoginText.text = "Logged In";

            WriteNewScore(User.DisplayName, PlayerPrefs.GetInt("HighScore"));
            string name = User.DisplayName;

            // Database
            DatabaseReference reference = FirebaseDatabase.DefaultInstance.GetReference("Highscore");

            reference.RunTransaction(AddScoreTransaction)
                 .ContinueWith(task => {
                     if (task.Exception != null)
                     {
                         Debug.Log(task.Exception.ToString());
                     }
                     else if (task.IsCompleted)
                     {
                         Debug.Log("Transaction complete.");
                     }
                 });
            //update UI
            addScorePressed = true;
            usernameText.text = name.ToString();
        //}
    }

    // Database:

    TransactionResult AddScoreTransaction(MutableData mutableData)
    {
        List<object> leaders = mutableData.Value as List<object>;

        if (leaders == null)
        {
            leaders = new List<object>();
        }
        else if (mutableData.ChildrenCount >= MaxScores)
        {
            // If the current list of scores is greater or equal to our maximum allowed number,
            // we see if the new score should be added and remove the lowest existing score.
            long minScore = long.MaxValue;
            object minVal = null;
            foreach (var child in leaders)
            {
                if (!(child is Dictionary<string, object>))
                    continue;
                long childScore = (long)((Dictionary<string, object>)child)["score"];
                if (childScore < minScore)
                {
                    minScore = childScore;
                    minVal = child;
                }
            }
            // If the new score is lower than the current minimum, we abort.
            if (minScore > score)
            {
                return TransactionResult.Abort();
            }
            // Otherwise, we remove the current lowest to be replaced with the new score.
            leaders.Remove(minVal);
        }

        // Now we add the new score as a new entry that contains the email address and score.
        Dictionary<string, object> newScoreMap = new Dictionary<string, object>();
        newScoreMap["score"] = score;
        newScoreMap["uid"] = name;
        leaders.Add(newScoreMap);

        // You must set the Value to indicate data at that location has changed.
        mutableData.Value = leaders;
        //return and log success
        return TransactionResult.Success(mutableData);
    }

}

I don’t know if this would help, as I am not sure I understand your code 100%.

I was having a similar issue. I was not able to update text of activate gameobjects when retrieving items from the database. the reason in my case is that I was using continueWith, meaning stuff was happening on a different thread but somehow Unity was not catching it. The solution was to use continueWithOnMainThread instead.

See the issue I posted on the firebase github here. Also this blog post might help.

2 Likes

Im not using continueWith and continueWithOnMainThread.

I found that Debug.Log stops there:

    public void UpdatePlayer()
    {
        if (auth.CurrentUser != null)
        {
            var user = auth.CurrentUser;
            Debug.LogFormat("User signed in succesfully: {0} ({1})", user.DisplayName, user.Email);
            // Deug.Log stops here
            userName = user.DisplayName;
            usernameText.text = user.DisplayName.ToString();
            Debug.Log("FirebaseInitialized");
        }

    }

Check Lines 77, 271, and 426 of what you posted. Pretty sure you’re using continueWith :stuck_out_tongue:

1 Like

You’re right.
I tried to use continueWithOnMainThread but I receive strange errors, I have no idea how to handle them…6348720--705714--1.png 6348720--705717--2.png

If you click on ‘show potential fixes’ it will probably suggest adding using Firebase.Extensions;. That’s what did the trick for me. I think the firebase extensions used to be a separate package, but I believe they have now been integrated into something else. Anyway, as soon as I added that line the error went away.

I hope this helps.

2 Likes

@frankoprus : how are you able to use “SetEditorDatabaseUrl”. I downloaded a new version of Firebase SDK and it shows that it’s deprecated/obsolete. I have no clue how to run it in the editor anymore. It’s pain in the ass to test it on mobile again and again.

4 Likes

Did you find the solution for that? I am trying it for the past two days and not found something yet

Try this and let me know if it works… @snirego75

FirebaseApp app;
    void Start()
    {
      app = FirebaseApp.DefaultInstance;
      Uri uri = new Uri("https://appname-0000.firebaseio.com/");//Your firebase url
      app.Options.DatabaseUrl = uri;
    }

SetEditorDatabaseUrl Deprecated ?

FirebaseApp.DefaultInstance.SetEditorDatabaseUrl(“https://yourapp-a6192.firebaseio.com/”); // SetEditorDatabaseUrl is deprecated in latest version of firebase please comment the line of code in script.

Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
var dependencyStatus = task.Result;
if (dependencyStatus == Firebase.DependencyStatus.Available) {
// Create and hold a reference to your FirebaseApp,
// where app is a Firebase.FirebaseApp property of your application class.
app = Firebase.FirebaseApp.DefaultInstance;

// Set a flag here to indicate whether Firebase is ready to use by your app.
} else {
UnityEngine.Debug.LogError(System.String.Format(
“Could not resolve all Firebase dependencies: {0}”, dependencyStatus));
// Firebase Unity SDK is not safe to use here.
}
});

Note : Open the link הוסף את Firebase לפרויקט Unity שלך  |  Firebase for Unity Read Step 5.