Unity Job系统详解原理和基础应用处理大量物体位置
概述
该脚本使用 Unity Job System 和 Burst Compiler 高效管理大量剑对象的位移计算与坐标更新。通过双缓冲技术实现无锁并行计算,适用于需要高性能批量处理Transform的场景。
核心类 SwordManager
成员变量
变量名 | 类型 | 说明 |
---|---|---|
swordPrefab | GameObject | 剑对象预制体 |
_deltaPositions | NativeArray<float3> | 每帧位移增量数据 (临时内存分配) |
_positionsBufferA/B | NativeArray<float3> | 双缓冲位置数据 (持久化内存分配) |
_swordTransforms | TransformAccessArray | 批量访问Transform的容器 |
_useBufferA | bool | 双缓冲切换标志 |
作业系统实现
1. 位移计算作业 Vector3AddPositionsJob
[BurstCompile(FloatMode = FloatMode.Fast)]
struct Vector3AddPositionsJob : IJobParallelFor
{
[ReadOnly] public NativeArray<float3> lastPositions; // 上一帧位置
[ReadOnly] public NativeArray<float3> deltaPositions; // 位移增量
[WriteOnly] public NativeArray<float3> currentPositions;// 计算结果
public void Execute(int index) =>
currentPositions[index] = lastPositions[index] + deltaPositions[index];
}
- 功能:并行计算每个剑的新位置
- 优化:使用
BurstCompile
加速数学运算,FloatMode.Fast
启用快速浮点模式
2. Transform更新作业 UpdateTransformsJob
[BurstCompile]
struct UpdateTransformsJob : IJobParallelForTransform
{
[ReadOnly] public NativeArray<float3> targetPositions;
public void Execute(int index, TransformAccess transform) =>
transform.position = targetPositions[index];
}
- 特性:直接修改Unity Transform组件
- 优势:避免主线程的GameObject开销
主要方法详解
1. 初始化 Start()
// 创建1000个剑对象
List<Transform> transforms = new List<Transform>();
for (int i = 0; i < 1000; i++) {
Instantiate(swordPrefab, randomPosition);
}
// 初始化双缓冲
_positionsBufferA = new NativeArray<float3>(count, Allocator.Persistent);
_positionsBufferB = new NativeArray<float3>(count, Allocator.Persistent);
2. 每帧更新 Update()
if (Input.GetKeyDown(KeyCode.Space))
{
// 分配临时位移数据
_deltaPositions = new NativeArray<float3>(..., Allocator.TempJob);
// 调度位移计算作业
var positionJob = new Vector3AddPositionsJob {
lastPositions = _useBufferA ? bufferA : bufferB,
currentPositions = _useBufferA ? bufferB : bufferA
};
_positionJobHandle = positionJob.Schedule(count, GetOptimalBatchSize());
// 调度Transform更新作业
var transformJob = new UpdateTransformsJob {
targetPositions = _useBufferA ? bufferB : bufferA
};
_transformJobHandle = transformJob.Schedule(_swordTransforms, _positionJobHandle);
_useBufferA = !_useBufferA; // 切换缓冲区
}
3. 批次优化 GetOptimalBatchSize()
int GetOptimalBatchSize() =>
Mathf.Max(32, totalCount / (SystemInfo.processorCount * 4));
- 算法:根据CPU核心数动态调整批次
- 目标:平衡线程开销与并行效率
内存管理策略
-
双缓冲机制
- 交替读写避免数据竞争
- Buffer A/B 使用
Allocator.Persistent
-
临时数据
_deltaPositions
使用Allocator.TempJob
- 在Job完成后通过
Dispose()
释放
-
销毁时清理
void OnDestroy() { JobHandle.Complete(); // 确保作业完成 _swordTransforms.Dispose(); _positionsBufferA/B.Dispose(); }
性能优化点
-
Burst编译加速
- 数学运算编译为高效Native代码
FloatMode.Fast
牺牲精度换取速度
-
Transform批量访问
- 使用
TransformAccessArray
减少API调用开销
- 使用
-
数据布局
- 结构体数据连续内存存储
- 避免CPU缓存失效
典型工作流程
注意事项
-
线程安全
- 确保Job完成前不修改NativeArray数据
- 使用
JobHandle.Complete()
同步
-
内存泄漏防范
- 严格匹配
Allocator
与Dispose()
- 在
OnDestroy
中释放持久化内存
- 严格匹配
-
移动端适配
- 测试不同处理器核心数的批次表现
- 调整
GetOptimalBatchSize
除数因子
-
Burst兼容性
- 避免在Job中使用非Burst兼容代码
- 注意
Managed
类型的使用限制