Half function/task is not executing

I’m currently working with the latest Firebase SDK v7.1.0 and Google Play Games for authentication, data storage and database reading. I have stuck for over 3 days trying to figure out what the problem is.

This is my code :-

using System;
using Firebase;
using UnityEngine;
using Firebase.Database;

public class UpdateChecker : MonoBehaviour
{
    public GameObject updateAvailableScreen;

    static string s_DatabaseURL = "firebase-database-path-is-hidden-for-privacy-reasons";
    static float s_DatabaseVersion = 1.0f;
    static float s_GameDataVersion = 1.0f;

    public static string databaseURL
    {
        get { return s_DatabaseURL; }
    }
    public static float databaseVersion
    {
        get { return s_DatabaseVersion; }
    }
    public static float gameDataVersion
    {
        get { return s_GameDataVersion; }
    }

    void Start()
    {
        //CheckForUpdates();
    }

    public void CheckForUpdates()
    {
        FirebaseDatabase.GetInstance(s_DatabaseURL).GetReferenceFromUrl(s_DatabaseURL + "/Version").GetValueAsync().ContinueWith(task =>
        {
            // Check if the task has any errors
            if (task.IsFaulted)
            {
                // Debug the errors
                FirebaseException exception = task.Exception.Flatten().InnerExceptions[0] as FirebaseException;
                Debug.Log(exception.Message);
            }
            // Check if the task has completed
            else if (task.IsCompleted)
            {
                // Parse the data
                DataSnapshot rawData = task.Result;
                float version = Convert.ToSingle(rawData.GetRawJsonValue());
                s_DatabaseVersion = version;

                Debug.Log("Database Version: " + s_DatabaseVersion + ", Application Version: " + s_GameDataVersion);

                // Check for data
                if (s_DatabaseVersion > s_GameDataVersion)
                {
                    // Update is available
                    Debug.Log("Update is available!");
                    updateAvailableScreen.SetActive(true);
                    Debug.Log(true);
                }
                else
                {
                    // Update is not available
                    Debug.Log("No updates!");
                }
            }
        });
    }
}

Here the updateAvailableScreen is a Canvas whose reference I have assigned in the Inspector.

When the update is available, the first Debug statement works which would notify gamer about an update. But when it comes to enabling the gameobject with SetActive(true), it does not work. I did a lot of research and no one seems to have this issue. I tried debugging and found that wherever I wrote the reference for updateAvailableScreen, Unity seems to return the whole function. Nothing below it gets executed. I messed around a lot, tried debugging but found no clue. Again, here, only half of the function/task is getting executed. I don’t know for what reason is this happening.

If anyone knows how to solve this, please be sure to answer. Thanks in advance.

I believe this is an issue with Unity’s lack of support for multi-threading within MonoBehaviour and other Unity classes such as GameObject.


This line here FirebaseDatabase.GetInstance(s_DatabaseURL).GetReferenceFromUrl(s_DatabaseURL + "/Version").GetValueAsync() tries to contact a database on the web, which may take some time (to get through proxies and web security and all that), causing it to block the main thread for a while, until there is a response. To get around this issue, a new task is created to handle this, allowing the Unity thread to continue without being blocked, and this task running in the background.


Once the task has completed, however, you can carry out methods with the response, but on a different thread. This is where the issue is. GameObject.SetActive only works on the main Unity thread. If called from another thread, it will cause an exception, AFAIK. (Test it yourself with this code):

if (s_DatabaseVersion > s_GameDataVersion)
{
     try
     {
           updateAvailableScreen.SetActive(true);
     }
     catch (System.Exception e)
     {
          Debug.LogError(e.Message);
     }
}

To get around this, you’ll need to queue a method to be run, in another script, which will run it on the Unity thread, once the task has completed. There might be a delay, but it’s the only way to run a method on the Unity thread from another thread. Here’s a script that might do that. It’s not the best (NOT THREAD-SAFE), but it’s very basic and should work for you:

public class Threader : MonoBehaviour
{
    static readonly ConcurrentQueue<Action> Actions = new ConcurrentQueue<Action>();

    void Update()
    {
        if (!Actions.IsEmpty)
        {
            while (Actions.TryDequeue(out var action))
            {
                action?.Invoke();
            }
        }
    }
}

Then, make sure this script is attached to a gameobject in your scene, and change your calling code to this:

Threader.Actions.Enqueue(() => updateAvailableScreen.SetActive(true));

This will hopefully run your methods on the Unity thread instead, producing the correct results. Hope this was the issue, and this solved it. Others, correct me if I’m mistaken and Firebase has nothing to do with threading. @HitarthPadaliya