我在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来更新屏幕,但失败了,因此直到真正出现单独的更新时,它才出现。
这是我对这些奇怪行为的假设,所以请让我知道这是否正确,以及是否有一种简洁(或记录)的方式来描述我所描述的内容。
答案 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";
});
};