【问题标题】:What Unity API's are not allowed in async callbacks?异步回调中不允许使用哪些 Unity API?
【发布时间】:2019-08-13 14:05:11
【问题描述】:

我在某个地方看到在 Unity 的线程中,您无法使用 Unity API。

我想知道一般异步回调是否也是这种情况(例如,在使用 WebSocketSharp 时分配给 WebSocket.OnMessage 的函数),如果是这样,那么有没有办法知道什么是允许的,什么是不允许的? t(即什么是“Unity API”)?


作为一个例子,当使用 WebSocketSharp 的 WebSocket.OnMessage 时,我把它放在了 MonoBehaviorStart 函数中:

// ws is a WebSocketSharp.WebSocket
// displayText is a UnityEngine.UI.Text

ws.OnMessage += (sender, evt) =>
  {
    // 1
    boo = UnityEngine.Random.Range(1, 1000).ToString();
    // 2
    displayText.text = "Heyoo";
  };

1 错误下的行(没有日志超出它)但没有显示错误消息。而当该行不在此回调中时(例如Update 的顶级),我可以看到它的结果没有问题。

至于2 下的行,Unity 中的 Inspector 会显示更新后的文本,但播放屏幕不会,直到我更新 Inspector 中的一个属性,好像文本字段确实更新了,但是当它需要时使用 Unity API 来更新屏幕,它失败了,所以直到单独的更新发生它才真正出现。

这是我对这些奇怪行为的假设,所以请让我知道这是否正确,以及是否有简洁(或记录)的方式来描述我所描述的内容。

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    async 通常的意思就是:不在主线程中。

    很难回答在主线程之后的其他线程中支持什么以及不支持什么......简而言之:大多数东西支持。

    UnityEngine.Random.Range(1, 1000).ToString(); 应该可以工作。 但是要小心分配!

    一种已知的解决方法是像回调工作线程一样创建并传递Actions 以执行回主线程,例如:

    public class MainThreadWorker : MonoBehaviour
    {
        // singleton pattern
        public static MainThreadWorker Instance;
    
        // added actions will be executed in the main thread
        ConcurrentQueue<Action> actions = new ConcurrentQueue<Action>();
    
        private void Awake()
        {
            if (Instance)
            {
                this.enabled = false;
                return;
            }
            Instance = this;
        }
    
        private void Update()
        {
            // execute all actions added since the last frame
            while (actions.TryDequeue(out var action))
            {
                action?.Invoke();
            }
        }
    
        public void AddAction(Action action)
        {
            if(action != null) actions.Enqueue(action);
        }
    }
    

    在你的场景中的某个地方,你现在可以将一个动作传回主线程,比如

    ws.OnMessage += (sender, evt) =>
        {
            MainThreadWorker.Instance.AddAction(()=>
                {
                    // 1
                    boo = UnityEngine.Random.Range(1, 1000).ToString();
                    // 2
                    displayText.text = "Heyoo";      
                });
        };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-05
      • 1970-01-01
      • 2016-06-09
      • 1970-01-01
      • 2010-12-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多