Unity2023.1.19_DOTS_JobSystem
上篇我们知道了DOTS是包含Entity Component System,Job System,Burst compiler三者的。接下来看下JobSystem的工作原理和具体实现。
简介:
官方介绍说:JobSystem允许您编写简单而安全的多线程代码,以便您的应用程序可以使用所有可用的CPU内核来执行代码。也就是说JobSystem是为多线程服务的一个模块。
JobSystem可以单独使用,但为了提高性能,也还应该使用Burst compiler,Burst compiler是专门为Unity的JobSystem编译而设计的。urst compiler改进了代码生成,从而提高了性能并减少了移动设备上的电池消耗。Burst compiler将在JobSystem之后再关注。
JobSystem和Burst compiler一起使用的时候,JobSystem工作效果最好。因为Burst不支持托管对象,所以需要使用非托管类型来访问Job中的数据。你可以使用blittable types,或者使用Unity内置的Native container对象,这是一个线程安全的c#本机内存包装器。NativeContainer对象还允许job访问与主线程共享的数据,而不是使用副本。
ECS为其进行了拓展Unity.Collections命名空间以包含其他类型的 NativeContainer:
NativeList - 可调整大小的 NativeArray,类似于List
NativeHashMap<T, R> - 键/值对,类似于Dictionary<T, R>
NativeMultiHashMap<T, R> - 每个键有多个值。
NativeQueue - 先进先出队列,类似于Queue
也可以在ECS中使用JobSystem创建高性能的面向数据代码。
Collections Package提供可在job和Burst-compiled代码中使用的非托管数据结构。
Unity使用原生的JobSystem处理原生代码使用多个工作线程,工作线程取决于你应用程序运行设备的CPU核的可用数量。
通常Unity默认在程序开始时在一个主线程上执行你的代码,你可以使用JobSystem在多个工作线程上执行你的代码,称之为多线程。
简单代码说明:
using UnityEngine;
using Unity.Collections;
using Unity.Jobs;// Job adding two floating point values together
// It implements IJob, uses a NativeArray to get the results of the job, and uses the Execute method with the implementation of the job inside it:public struct MyJob : IJob
{public float a;public float b;public NativeArray<float> result;public void Execute(){result[0] = a + b;}
}
下面的例子建立在MyJob任务上,在主线程上调度一个任务:
using UnityEngine;
using Unity.Collections;
using Unity.Jobs;public class MyScheduledJob : MonoBehaviour
{// Create a native array of a single float to store the result.// Using a NativeArray is the only way you can get the results of the job, whether you're getting one value or an array of values.NativeArray<float> result;// Create a JobHandle for the job// 给任务创建一个任务处理JobHandle handle;// Set up the job// 创建一个任务public struct MyJob : IJob{public float a;public float b;public NativeArray<float> result;public void Execute(){result[0] = a + b;}}// Update is called once per frame// 每一帧更新void Update(){// Set up the job data 设置任务数据result = new NativeArray<float>(1, Allocator.TempJob);MyJob jobData = new MyJob{a = 10,b = 10,result = result};// Schedule the job 安排任务handle = jobData.Schedule();}private void LateUpdate(){// Sometime later in the frame, wait for the job to complete before accessing the results.// 稍后在框架中,等待作业完成后再访问结果。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();}}
跟一个测试:
using UnityEngine;
using Unity.Collections;
using Unity.Jobs;public class MyScheduledJob : MonoBehaviour
{// Create a native array of a single float to store the result.// Using a NativeArray is the only way you can get the results of the job, whether you're getting one value or an array of values.NativeArray<float> result;// Create a JobHandle for the job// 给任务创建一个任务处理JobHandle handle;// Set up the job// 创建一个任务public struct MyJob : IJob{public float a;public float b;public NativeArray<float> result;public void Execute(){result[0] = a + b;}}// Update is called once per frame// 每一帧更新void Update(){// Set up the job data 设置任务数据result = new NativeArray<float>(1, Allocator.TempJob);MyJob jobData = new MyJob{a = 10,b = 10,result = result};// Schedule the job 安排任务handle = jobData.Schedule();}private void LateUpdate(){// Sometime later in the frame, wait for the job to complete before accessing the results.// 稍后在框架中,等待作业完成后再访问结果。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();}}
意思大概是这样了,具体实践具体看!!
参考文档:
官方文档
Unity - Manual: Job system overview (unity3d.com)
Collections package | Collections | 2.2.1 (unity3d.com)
Unity - Manual: Thread safe types (unity3d.com)
这个博主系列的讲到了DOTS,可以看一下:
DOTS ECS_铸梦xy的博客-CSDN博客