JobSystem :
unity提供的一套多线程解决方案,使用这个东西可以极大的提升游戏的运行效率
NativeContainer
NativeContainer 是一种托管值类型,为本机内存提供了一个相对安全的 C# 封装器。它包含一个指向非托管分配的指针。与 Unity C# 作业系统一起使用时,NativeContainer 允许作业访问与主线程共享的数据,而不是使用副本。
如何创建一个job
首先创建一个结构体 实现IJob接口,在接口内部实现Excute()方法,作业的任务处理就放在这个函数之中
NativeArray result 是一个返回结果的数组,这是一种共享的数组
[BurstCompile]
public struct MyJob : IJob
{
public float a;
public float b;
public NativeArray<float> result;
public void Execute()
{
result[0] = a + b;
}
}
如何调度Job
在主线程的update里面可以写入一下代码
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);
// 设置作业数据
MyJob jobData = new MyJob();
jobData.a = 2f;
jobData.b = 3f;
jobData.result = result;
//调度作业
JobHandle handle = jobData.Schedule();
//等待作业的完成
jobData.Complete();
float res = result[0];
Debug.Log(res);
//释放托管资源
result.Dispose();
然后运行即可
JobHandle和依赖项
一个线程的执行需要在另一个线程的结束之后
调用作业的 Schedule 方法时,将返回 JobHandle。可以在代码中使用 JobHandle 作为其他作业的依赖项。如果一个作业依赖于另一个作业的结果,则可以将第一个作业的 JobHandle 作为参数传递给第二个作业的 Schedule 方法,如下所示:
JobHandle firstJobHandle = firstJob.Schedule();
secondJob.Schedule(firstJobHandle);
以下实例实现两个作业的调度
// 将两个浮点值相加的作业
[BurstCompile]
public struct MyJob : IJob
{
public float a;
public float b;
public NativeArray<float> result;
public void Execute()
{
result[0] = a + b;
}
}
// 将一个值加一的作业
[BurstCompile]
public struct AddOneJob : IJob
{
public NativeArray<float> result;
public void Execute()
{
result[0] = result[0] + 1;
}
}
主线程
private void Update()
{
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);
// 设置作业数据
MyJob jobData = new MyJob();
jobData.a = 2f;
jobData.b = 3f;
jobData.result = result;
AddOneJob incJobData = new AddOneJob();
incJobData.result = result;
//调度作业
JobHandle handle = jobData.Schedule();
JobHandle secondHandle = incJobData.Schedule(handle);
//等待作业的完成
secondHandle.Complete();
float res = result[0];
Debug.Log(res);
result.Dispose();
}
IJobParallelFor
在调度作业时,只能有一个作业正在执行一项任务。在游戏中,通常希望对大量对象执行相同的操作。这个接口可以实现一个作业执行多个任务
// 将两个浮点值相加的作业
public struct MyParallelJob : IJobParallelFor
{
[ReadOnly]
public NativeArray<float> a;
[ReadOnly]
public NativeArray<float> b;
public NativeArray<float> result;
public void Execute(int i)
{
result[i] = a[i] + b[i];
}
}
NativeArray<float> a = new NativeArray<float>(2, Allocator.TempJob);
NativeArray<float> b = new NativeArray<float>(2, Allocator.TempJob);
NativeArray<float> result = new NativeArray<float>(2, Allocator.TempJob);
a[0] = 1.1;
b[0] = 2.2;
a[1] = 3.3;
b[1] = 4.4;
MyParallelJob jobData = new MyParallelJob();
jobData.a = a;
jobData.b = b;
jobData.result = result;
// 调度作业,为结果数组中的每个索引执行一个 Execute 方法,且每个处理批次只处理一项
JobHandle handle = jobData.Schedule(result.Length, 1);
// 等待作业完成
handle.Complete();
// 释放数组分配的内存
a.Dispose();
b.Dispose();
result.Dispose();