异步回调中不允许使用哪些Unity API?

时间:2019-08-12 22:37:53

标签: c# unity3d

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

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


例如,当使用WebSocketSharp的WebSocket.OnMessage时,我将其放在Start的{​​{1}}函数中:

MonoBehavior

// 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下的行,Unity中的检查器显示更新的文本,但是“播放”屏幕不会显示,直到我更新了检查器中的属性,就像文本字段确实得到更新一样,但是当它需要使用Unity API来更新屏幕,但失败了,因此直到真正出现单独的更新时,它才出现。

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

1 个答案:

答案 0 :(得分:3)

async的确切含义通常是:不在主线程中。

很难回答受支持的内容,而主线程则无法回答什么……简而言之:大多数内容不受支持。

UnityEngine.Random.Range(1, 1000).ToString();应该可以工作。 但是请谨慎处理作业!

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

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";      
            });
    };