How to Develop a Game
Thread
PublishDate: 2025-06-01 | CreateDate: 2025-06-01 | LastModify: 2025-06-01 | Creator:ljf12825

Unity中的线程机制和使用方式,包括:

Unity线程模型概览

Unity整个运行环境围绕主线程组织,它的执行流程大致如下:

主线程Unity Loop):
 ├─ Start()
 ├─ Update()
 ├─ 渲染提交
 ├─ 动画更新
 ├─ 物理处理同步 PhysX
 └─ LateUpdate()

主线程的作用:

Unity API的线程限制

Unity引擎的绝大多数API不是线程安全的,只能在主线程中访问

常见不可在子线程中调用的内容:

类型示例
场景对象transform.positiongameObject.SetActive()
UI 操作Text.textImage.spriteCanvasGroup.alpha
加载资源Resources.LoadAssetBundle.LoadAsset
UnityEventInvoke()AddListener()
摄像机/渲染设置Camera.fieldOfViewRenderSettings.ambientLight

为什么大多数Unity API不是线程安全的

线程安全是指多个线程同时访问某个资源时,不会出现数据竞争、资源冲突或者状态不一致; 换句话说,线程安全的代码能保证即使多个线程同时调用,也不会导致程序崩溃或出现错误

1.引擎设计的历史和架构

2.性能考虑

3.复杂的状态和资源管理

4.引擎内部很多操作并非原子性

Unity中使用多线程的四种方式

1.Thread类(低级方案)

适用场景:非常简单的子线程计算任务

using System.Threading;

void Start()
{
    Thread t = new Thread(() =>{
        int result = HeavyCompute();
        Debug.Log("不能再这里操作 Unity API!");
    });
    t.Start();
}

缺点:

2.Task + async/await(推荐方式)

适合:异步加载、复杂逻辑封装

async void Start()
{
    int result = await Task.Run(() => HeavyCompute());
    // 回到主线程,可以安全使用 Unity API
    Debug.Log($"计算结果:{result}");
}

优点:

3.Unity Job System(高性能并发)

适用场景:大量数据并发处理(如物理模拟、AI批量计算)

using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;

[BurstCompile]
public struct MyJob : IJob
{
    public NativeArray<int> data;

    public void Execute()
    {
        for (int i = 0; i < data.Length; i++)
            data[i] = data[i] * 2;
    }
}

void Start()
{
    NativeArray<int> arr = new NativeArray<int>(100, Allocator.TempJob);

    for (int i = 0; i < arr.Length ++i) arr[i] = i;

    var job = new MyJob { data = arr };
    JobHandle handle = job.Schedule();
    handle.Complete();

    Debug.Log(arr[10]);
    arr.Dispose();
}

特点:

4.Unity DOTS (ECS + Job + Burst)

适用场景:高度并发的大型项目(如模拟类游戏、成千上万个实体)
ECS配合Job System形成完整的数据驱动架构
优点:

回到主线程的方法

场景:你在子线程或Task中获得数据,想更新UI或GameObject

方法一、使用async/await自动切换回主线程

async void LoadData()
{
    string json = await Task.Run(() => File.ReadAllText("config.json"));
    myText.text = json; // 主线程
}

方法二、自己封装一个主线程执行器

public class MainThreadDispatcher : MonoBehaviour
{
    private static readonly Queue<Action> actions = new Queue<Action>();

    public static void Enqueue(Action action)
    {
        lock (actions)
        {
            actions.Enqueue(action);
        }
    }

    void Update()
    {
        lock (actions)
        {
            while (actions.Count > 0)
                actions.Dequeue()?.Invoke();
        }
    }
}

使用:

ThreadPool.QueueUserWorkItem(_ => {
    string data = HeavyLoad();
    MainThreadDispatcher.Enqueue(() => myText.text = data);
});

使用多线程的场景

主线程外只用于非Unity API的计算,不允许访问Unity对象,执行完毕后记得退回主线程

Unity引擎内部是多线程的

虽热大多数逻辑跑在主线程,但Unity引擎内部会使用多线程来提升性能

功能是否多线程说明
PhysX 物理引擎多线程Unity 会自动并行化处理
Audio 音频系统多线程音频解码、播放管理在后台
渲染管线(SRP)多线程在某些平台支持多线程提交渲染指令
Animation 系统多线程(部分)有些姿态计算在 Job 系统中进行