概述
现代 CPU 拥有 4-16 个核心,但 Unity 传统的 MonoBehaviour.Update 只在单线程上执行,其他核心大部分时间空闲。
Job System 让开发者安全地将工作分发到多个线程。Burst Compiler 则将 C# 代码编译为高度优化的原生机器码(利用 SIMD 指令集)。两者结合,可以将 CPU 密集型任务加速 10-50 倍。
1. 为什么需要 Job System
1 2 3 4 5 6 7 8 9
| void Update() { for (int i = 0; i < particles.Length; i++) { particles[i].Position += particles[i].Velocity * Time.deltaTime; } }
|
Job System 将工作切分为小块,分发到所有可用核心:
1 2 3 4 5 6 7 8 9
| var job = new UpdateParticleJob { positions = positions, velocities = velocities, deltaTime = Time.deltaTime };
var handle = job.Schedule(particlesCount, 128); handle.Complete();
|
2. Job 基础
2.1 IJobParallelFor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| using Unity.Collections; using Unity.Jobs; using Unity.Burst;
[BurstCompile] public struct UpdatePositionJob : IJobParallelFor { public NativeArray<Vector3> positions; public NativeArray<Vector3> velocities; [ReadOnly] public float deltaTime;
public void Execute(int index) { positions[index] = velocities[index] * deltaTime; } }
public class JobExample : MonoBehaviour { private NativeArray<Vector3> _positions; private NativeArray<Vector3> _velocities; private const int Count = 100000;
private void Start() { _positions = new NativeArray<Vector3>(Count, Allocator.Persistent); _velocities = new NativeArray<Vector3>(Count, Allocator.Persistent); }
private void Update() { var job = new UpdatePositionJob { positions = _positions, velocities = _velocities, deltaTime = Time.deltaTime };
var handle = job.Schedule(Count, 64); handle.Complete(); }
private void OnDestroy() { _positions.Dispose(); _velocities.Dispose(); } }
|
2.2 依赖链
多个 Job 可以串联,形成依赖链:
1 2 3 4
| var velocityHandle = velocityJob.Schedule(count, 64); var positionHandle = positionJob.Schedule(count, 64, velocityHandle); var collisionHandle = collisionJob.Schedule(count, 64, positionHandle); collisionHandle.Complete();
|
3. Burst Compiler
只需要在 Job 结构体上加 [BurstCompile]。
3.1 性能对比
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| for (int i = 0; i < 1000000; i++) result[i] = Mathf.Sin(i * 0.001f);
[BurstCompile] public struct SinJob : IJobParallelFor { public NativeArray<float> results; public void Execute(int index) { results[index] = math.sin(index * 0.001f); } }
|
3.2 Burst 的限制
1 2 3 4 5 6 7 8 9 10 11 12
| 不能使用: - 引用类型(class、string、object) - 托管数组(T[]) - 异常(try-catch) - 委托(Action、Func) - 反射 - 虚方法调用
可以使用: - 值类型(struct、enum、int、float) - NativeContainer - Unity.Mathematics 类型(float3、quaternion)
|
4. 性能基准
| 操作 |
单线程 C# |
Job + Burst |
提升 |
| 100K 粒子更新 |
~3.5ms |
~0.3ms |
11x |
| 500K 向量计算 |
~18ms |
~0.8ms |
22x |
| 100K AABB 碰撞检测 |
~8ms |
~0.4ms |
20x |
| 1M sin 计算 |
~45ms |
~3ms |
15x |
总结
- Job System 将工作分配到多核 CPU,依赖链自动管理执行顺序
- Burst Compiler 将 Job 编译为高效机器码,性能提升 10-50 倍
- NativeContainer 是 Job 的唯一数据容器,需手动管理生命周期
- 适合:大量并行计算、物理模拟、粒子系统、路径查找
下一篇将进入 Netcode for GameObjects,实现 Unity 多人游戏的网络通信。