Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regarding the new Firebase SDK for Unity and Threading Tasks

I have a more general question regarding Unity C# and the brand new Firebase SDK. I've looked through all of the new documentation and haven't seen an answer to this yet. If you retrieve data from the database below, it doesn't allow you to execute methods like Instantiate inside this function because it is not happening on the main thread. How would you go about doing this? TLDR I want to know how to execute game functions after or while retrieving stuff from Firebase.

   FirebaseDatabase.DefaultInstance
    .GetReference("Scenes").OrderByChild("order")
    .ValueChanged += (object sender2, ValueChangedEventArgs e2) => {
      if (e2.DatabaseError != null) {
        Debug.LogError(e2.DatabaseError.Message);
        }
        scenes = asset.text.Split('\n');
        return;
      }
      if (e2.Snapshot != null && e2.Snapshot.ChildrenCount > 0) {
        sceneCollection.Clear();
        foreach (var childSnapshot in e2.Snapshot.Children) {
          var sceneName = childSnapshot.Child("name").Value.ToString(); 
          sceneCollection.Add( new SceneItem(sceneName, 0));

          // I WANTED TO INSTANTIATE SOMTHING HERE

        }

      }
    };
like image 512
Teddy Avatar asked Oct 17 '22 22:10

Teddy


1 Answers

(Ben from the Firebase team here)

This is now fixed as Stewart says below:

https://firebase.google.com/support/release-notes/unity#1.0.1

I'm leaving the code below in case anyone finds it useful to be able to marshal to the ui thread from a background thread. Once you install this synchronizationcontext, you can use it like any other .Net SynchronizationContext:

https://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext(v=vs.110).aspx

UnitySynchronizationContext.Install();

class UnitySynchronizationContext : SynchronizationContext {
  static UnitySynchronizationContext _instance = null;
  GameObject gameObject;
  Queue<Tuple<SendOrPostCallback, object>> queue;

  private UnitySynchronizationContext() {
    gameObject = new GameObject("SynchronizationContext");
    gameObject.AddComponent<SynchronizationContextBehavoir>();
    queue =
      gameObject.GetComponent<SynchronizationContextBehavoir>()
        .Queue;
  }

  public static void Install() {
    if (SynchronizationContext.Current == null)
    {
      if (_instance == null)
      {
        _instance = new UnitySynchronizationContext();
      }
      SynchronizationContext.SetSynchronizationContext(_instance);
    }
  }

  public override void Post(SendOrPostCallback d, object state) {
    lock (queue)
    {
      queue.Enqueue(new Tuple<SendOrPostCallback, object>(d, state));
    }
  }

  class SynchronizationContextBehavoir : MonoBehaviour {
    Queue<Tuple<SendOrPostCallback, object>> callbackQueue
        = new Queue<Tuple<SendOrPostCallback, object>>();

    public Queue<Tuple<SendOrPostCallback, object>>
        Queue { get { return callbackQueue; }}

    IEnumerator Start() {
      while (true)
      {
        Tuple<SendOrPostCallback, object> entry = null;
        lock (callbackQueue)
        {
          if (callbackQueue.Count > 0)
          {
            entry = callbackQueue.Dequeue();
          }
        }
        if (entry != null && entry.Item1 != null)
        {
          try {
            entry.Item1(entry.Item2);
          } catch (Exception e) { 
            UnityEngine.Debug.Log(e.ToString());
          }
        }
        yield return null;
      }
    }
  }
}
like image 152
Benjamin Wulfe Avatar answered Oct 21 '22 01:10

Benjamin Wulfe