I saw somewhere that within a Thread in Unity, you couldn't use Unity API's.
I'm wondering if this is also the case for async callbacks in general (for example a function assigned to WebSocket.OnMessage
when using WebSocketSharp), and if so then is there a way to know what is allowed and what isn't (ie what are "Unity API's")?
As an example, when using WebSocketSharp's WebSocket.OnMessage
, I put this in my Start
function of a 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";
};
The line under 1
errors (no logs just beyond it) but no error message shows. Whereas when that line is not inside this callback (top-level of Update
for example), I can see its result no problem.
As for the line under 2
, the Inspector in Unity shows the updated text, but the Play screen does not, until I update an attribute in the Inspector, as if the text field did get updated, but when it needed to use a Unity API to update the screen, it failed, so it's not until a separate update happens that it actually appears.
That's my hypothesis for these odd behaviors, so please let me know if that is correct, and if there's a succinct (or documented) way to describe what I'm describing.
async
in general means exactly this: Not in the main thread.
It is hard to answer what is supported and what not in other threads then the mainthread ... short: Most things are not supported.
The UnityEngine.Random.Range(1, 1000).ToString();
should work. But be carefull with assignments!
A known workaround is to create like a callback worker and pass Action
s to execute back to the main thread like eg:
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);
}
}
Having this in your scene somewhere you can now pass an action back to the main thread like
ws.OnMessage += (sender, evt) =>
{
MainThreadWorker.Instance.AddAction(()=>
{
// 1
boo = UnityEngine.Random.Range(1, 1000).ToString();
// 2
displayText.text = "Heyoo";
});
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.