关于用于 Unity 和线程任务的新 Firebase SDK

Posted

技术标签:

【中文标题】关于用于 Unity 和线程任务的新 Firebase SDK【英文标题】:Regarding the new Firebase SDK for Unity and Threading Tasks 【发布时间】:2017-03-26 07:22:27 【问题描述】:

关于 Unity C# 和全新的 Firebase SDK,我有一个更普遍的问题。我浏览了所有新文档,但还没有看到答案。如果您从下面的数据库中检索数据,它不允许您在此函数中执行诸如 Instantiate 之类的方法,因为它不在主线程上发生。你会怎么做呢? TLDR 我想知道如何在从 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

        

      
    ;

【问题讨论】:

我还没查!但是如果你用谷歌搜索“Unity3D 回调到主线程”,你会发现很多关于这个例子的讨论......forum.unity3d.com/threads/mainthread-function-caller.348198...... 我建议从资产商店获取处理线程的(优秀)包之一;它将解决问题。令人惊讶的是 Firebase 没有“投入一些东西”来处理这个问题。 非常感谢 JB 我会试试的。另外,我将向 Firebase 团队提出功能请求。 对,很奇怪他们没有解决这个问题。很抱歉我没有机会看它;你很确定他们没有包含返回主线程的机制吗? BTW 在那个代码中你 += ... 我鼓励你在你的脚本中把它作为一个单独的函数,并且 += 那个函数 - 它只是更清楚到底发生了什么你知道吗? 【参考方案1】:

(来自 Firebase 团队的 Ben)

正如斯图尔特所说,现在已修复:

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

我将留下下面的代码,以防有人发现能够从后台线程编组到 ui 线程很有用。安装此同步上下文后,您可以像使用任何其他 .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;
      
    
  

【讨论】:

嗨本杰明伍尔夫。你是说你在 Firebase 吗?? 我会试一试的。没有必要道歉。你做得很好。 感谢您发布此内容。 @BenjaminWulfe 抱歉,本杰明,请查看我在此问题的已接受答案上发表的评论。谢谢!【参考方案2】:

我们已在 1.0.1 版本中修复了此问题: https://firebase.google.com/support/release-notes/unity#1.0.1

您可以从以下位置下载最新版本: https://firebase.google.com/docs/unity/setup

干杯,

Stewart(来自 Firebase 团队)

【讨论】:

嗨!我可以从 CreateUserWithEmailAndPasswordAsync 的回调中调用与统一相关的方法,但是如果我切换到 .net 4.6,然后执行 Assets->Play Services Resolver->Version Handler->Update 我得到“只能从主线程调用方法”。这是 .net 4.6 中的一个已知问题吗?我们需要自己处理线程同步吗?

以上是关于关于用于 Unity 和线程任务的新 Firebase SDK的主要内容,如果未能解决你的问题,请参考以下文章

用于理解 Java 中的多线程的简单任务

主线程和worker分离

Firebase 使任务仅在主线程上执行,导致 Unity 冻结

关于线程池的工作队列类型

unity渲染性能优化

Unity 4.0 中的新动画系统——MecAnim