众所周知,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();
}