Unity C# Job System介绍(三) Job的创建和调度

创建Jobs

Unity - Manual: Creating jobs​docs.unity3d.com

为了在Unity中创建一个job你需要实现IJOb接口。IJob允许你调度一个job,和其他jobs并发执行。Unity - Manual: Creating jobs为了在Unity中创建一个job你需要实现IJOb接口。IJob允许你调度一个job,和其他jobs并发执行。

注意:“job”是Unity中所有实现了IJob接口的结构的总称。

为了创建一个job,你需要: 创建一个实现IJob的结构体 添加job需要使用的成员变量(可以是blittable类型或NativeContainer类型) * 在结构体中添加一个叫Execute的方法并将job的具体逻辑实现放在里面

当job执行的时候,Excute方法在单个核心上运行一次

注意:当设计你的job时,记住你是在一份数据的拷贝上进行操作的,除了在使用NativeContainer的情况下。所以,在主线程访问一个job中数据的唯一方法就是将数据写入NativeContainer。

一个简单job定义的例子

// Job adding two floating point values together
public struct MyJob : IJob
{
    public float a;
    public float b;
    public NativeArray<float> result;

    public void Execute()
    {
        result[0] = a + b;
    }
}

调度Jobs

Unity - Manual: Scheduling jobs​docs.unity3d.com

为了在主线程中调度一个job,你必须: 实例化一个job 填充job中的数据 * 调用Schedule方法

在合适的时间调用Schedule将job放入到job的执行队列中。一旦job被调度,你不能中途打断一个job的执行。

注意:你只能从主线程中调用Schedule

调度一个job的例子

// Create a native array of a single float to store the result. This example waits for the job to complete for illustration purposes
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);

// Set up the job data
MyJob jobData = new MyJob();
jobData.a = 10;
jobData.b = 10;
jobData.result = result;

// Schedule the job
JobHandle handle = jobData.Schedule();

// Wait for the job to complete
handle.Complete();

// All copies of the NativeArray point to the same memory, you can access the result in "your" copy of the NativeArray
float aPlusB = result[0];

// Free the memory allocated by the result array
result.Dispose();

JobHandle和依赖关系

当你调用Schedule方法时会返回一个JobHandle。你可以在代码中使用JobHandle作为其他jobs的依赖关系。如果一个job依赖于另一个job的结果,你可以将第一个job的JobHandle作为参数传递给第二个job的Schedule方法,像这样:

JobHandle firstJobHandle = firstJob.Schedule();
secondJob.Schedule(firstJobHandle);

组合依赖关系

如果一个job有多个依赖项,你可以使用JobHandle.CombineDependencies方法来合并他们。CombineDependencies允许你将他们传递给Schedule方法。

NativeArray<JobHandle> handles = new NativeArray<JobHandle>(numJobs, Allocator.TempJob);

// Populate `handles` with `JobHandles` from multiple scheduled jobs...

JobHandle jh = JobHandle.CombineDependencies(handles);

在主线程中等待jobs结束

使用JobHandle来让你的代码在主线程等待直到你的job执行完毕。为了做到这样,需要在JobHandle上调用Complete方法。这样的话,你就确定主线程可以安全访问job之前使用的NativeContainer。

注意:jobs不是在你调度他们的时候就立刻开始执行。如果你在主线程中等待job,并且你需要访问job正在使用的NativeContainer,你可以调用JobHandle.Complete方法。这个方法会刷新内存缓存中的jobs并开始执行。调用JobHandele的Complete会将job的NativeContainer类型数据的归属权交还给主线程。你需要在JobHandle上调用Complete来在主线程再次安全地访问这些NativeContainer类型。你也可以调用一个由job依赖产生的JobHandle的Complete方法来将数据的归属权交还给主线程。举例来说,你可以调用jobA的Complete方法,或者你可以调用依赖于jobA的jobB的Complete方法。两种方法都可以让你在调用Complete后在主线程安全访问jobA使用的NativeContainer类型。

否则,如果你不需要对数据的访问,但你需要明确地刷新这个批次的job。为了做到这点,调用静态方法JobHandle.ScheduleBatchedJobs。注意这个调用会对性能产生负面的影响。

一个关于多重job和依赖的例子

job的代码:

// Job adding two floating point values together
public struct MyJob : IJob
{
    public float a;
    public float b;
    public NativeArray<float> result;

    public void Execute()
    {
        result[0] = a + b;
    }
}

// Job adding one to a value
public struct AddOneJob : IJob
{
    public NativeArray<float> result;

    public void Execute()
    {
        result[0] = result[0] + 1;
    }
}

主线程代码:

// Create a native array of a single float to store the result in. This example waits for the job to complete
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);

// Setup the data for job #1
MyJob jobData = new MyJob();
jobData.a = 10;
jobData.b = 10;
jobData.result = result;

// Schedule job #1
JobHandle firstHandle = jobData.Schedule();

// Setup the data for job #2
AddOneJob incJobData = new AddOneJob();
incJobData.result = result;

// Schedule job #2
JobHandle secondHandle = incJobData.Schedule(firstHandle);

// Wait for job #2 to complete
secondHandle.Complete();

// All copies of the NativeArray point to the same memory, you can access the result in "your" copy of the NativeArray
float aPlusB = result[0];

// Free the memory allocated by the result array
result.Dispose();

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用UnityJob System来构建Mesh可以提高游戏的性能,因为它可以在多个CPU核心上同时处理数据。 首先,你需要为你的Mesh数据创建一个结构体,以便Job System可以处理它。例如,你可以创建一个包含所有Mesh数据的结构体,如下所示: ``` struct MeshData { public Vector3[] vertices; public int[] triangles; ... } ``` 接下来,你需要创建一个Job,用于生成Mesh。你可以使用IJobParallelFor或IJobForEach来处理每个顶点或三角形。例如,如果要处理每个顶点,可以编写以下代码: ``` struct GenerateMeshJob : IJobParallelFor { public MeshData meshData; public void Execute(int i) { // Generate vertex data meshData.vertices[i] = ... } } ``` 然后,你需要在主线程中分配和初始化MeshData结构体,并将其传递给Job: ``` var meshData = new MeshData(); // Initialize meshData vertices, triangles, etc. var job = new GenerateMeshJob() { meshData = meshData }; var jobHandle = job.Schedule(meshData.vertices.Length, 64); ``` 最后,你需要等待Job完成,并将数据写入Mesh: ``` jobHandle.Complete(); var mesh = new Mesh(); mesh.vertices = meshData.vertices; mesh.triangles = meshData.triangles; ... ``` 需要注意的是,使用Job System构建Mesh需要一定的编程经验和技巧,因为它涉及到多线程编程和数据同步等问题。因此,如果你是新手开发者,建议先熟悉Job System的基本用法和原理,然后再尝试使用它来构建Mesh。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值