【开发问题】unity如何在子线程调用unity的api
众所周知,unity不推荐多线程运行,防止线程不安全。有关场景和物体的操作只能在主线程中进行。更推荐用协程来代替。但是没办法,有的场景就还是得用线程方便,不然太浪费资源了。可以在主线程注册一个任务队列,用委托,update里不停读取。
unity对物体的操作只允许在主线程中,如果想要操作。可以使用unitask,但这个是个额外的库,需要下载。
直接通过unity可以如下实现。
需求假设:开启一个线程不断接受来自一个后端的消息,当接收到指定消息,游戏做出响应的变动,如更改text,打印log
我们可以用委托的方式实现。
// 在主线程中,如login类中
//-----------------------------
// 定义一个新的委托类型
private delegate void TaskDelegate();
// 修改任务队列的类型
private static readonly Queue<TaskDelegate> Tasks = new();
// 线程安全的任务队列,这个ZinxClient.OnMessageReceivedHandler是我定义在ZinxClient类中的一个委托:
// public delegate void OnMessageReceivedHandler(int msgId, string message);
public static void EnqueueTask(int msgId, string msg, ZinxClient.OnMessageReceivedHandler action)
{
lock (QueueLock)
{
// 创建一个新的TaskDelegate,这个TaskDelegate封装了一个方法,这个方法接收msgId和msg作为参数,并调用action
TaskDelegate task = () => action(msgId, msg);
Tasks.Enqueue(task);
}
}
public static void ExecuteTasks()
{
lock (QueueLock)
{
while (Tasks.Count > 0)
{
var task = Tasks.Dequeue();
task?.Invoke();
}
}
}
// 队列锁
private static readonly object QueueLock = new();
//------------
// 之后在子线程中,如果要调用游戏物体的操作,将其加入到主线程的这个任务队列中,最后在主线程的update中不断执行这个队列。
// 示例子线程方法
private void SubThreadMethod()
{
// 加入主线程任务队列,其中OnMessageReceived是当前子线程类中的一个事件:
// public event OnMessageReceivedHandler OnMessageReceived;
Login.EnqueueTask(msgId,msg,OnMessageReceived);
}
// 在主线程 Update中执行主线程任务队列中的方法
private void Update()
{
// 执行任务队列
ExecuteTasks();
}