【UnityDOTS 一】JOBS理解

文章介绍了DOTS框架中的JOBS系统,用于简化多线程编程。JOBS是基于Struct的,可以并行或顺序执行,依赖于JobHandle来管理执行顺序和依赖关系。关键点包括使用Blittable类型数据,避免数据冲突和内存泄漏,并注意JOB的生命周期和依赖安全检查。
摘要由CSDN通过智能技术生成

DOTS中的JOBS理解

前言

随着DOTS1.0的正式发布,作为众多菜鸟程序员中的一个,在下准备开坑DOTS了,希望能一直更新下去,这一篇就纯试试水。


一、JOBS是什么?

DOTS中的基础一环就是JOBS(job system)。当然这个可以脱离DOTS来单独使用,其核心就是多线程编程。JOBS帮助我们封装好了多线程的分配与管理,多线程的调度、依赖等问题。附带一句:如果你个人技术很牛逼,也可以自己实现多线程来加速你的游戏逻辑。

二、使用步骤

1.构建一个JOB结构体

构建一个Struct来继承各种IJOB(Unity提供的),至于用哪一种得看具体的需求,这里示例用的IJobParallelForTransform。这个是Unity提供的,专门用来并行执行Trasform操作的Job类。

代码如下(示例):

struct CubesJob : IJobParallelForTransform
    {
        [ReadOnly] public float elapsedTime;

        public void Execute(int index, TransformAccess transform)
        {
            var distance = Vector3.Distance(transform.position, Vector3.zero);
            transform.localPosition += Vector3.up * math.sin(elapsedTime * 3f + distance * 0.2f);
        }
    }

注意点:一定要区分JOB的用途,带Parallel字眼的Job都是并行的,即多个线程来同时执行。有一些JOB,可以通过Job调度的方式来并行执行,或者按顺序执行(在单独线程,或者主线程中)。

2.主线程调度

在你自己的主线程代码中构建这个Job,因为是Struct所以也不会有GC问题。这里我在一个MonoBehaviour脚本的Update中创建一个Job并进行调度,同时用Complete方法告诉主线程的这个Update你需要等待JOB执行完,再执行后面的操作。个人估计这里有个类似Task的Wait方法。

void Update()
        {
           
           var cubesJob = new CubesJob
             {
               elapsedTime = Time.time,
             };
            var cubesJobhandle = waveCubesJob.Schedule(transformAccessArray);
            cubesJobhandle.Complete();
            
        }

3.有关Job中能用的数据Blittable类型

因为JOB调度底层是C++中的JOBSystem,所以要使用C#与C++兼容的数据才可以在JOB中访问。
Blittable类型的数据,托管内存与非托管内存具有相同的表现形式。
所以C#传给JOB中的数据,如果是一些非Blittable类型要转一下。
还有一些集合类型的容器类型:NativeArray,NativeSlice,TransformAccess,TransformAccessArray(上面的例子用的),NativeList,NativeHashMap等

这些非托管内存,记得调用Dispose手动释放(非托管内存)

注意: C#中的boolean和C++中的不一样,一个是4字节,一个是1字节,所以不能用。

非托管类型容器类使用时还要注意生命周期的声明。
Persistent:长生命周期内存,创建效率最低
TempJob:Job中存在的短生命周期,存在4帧以上没有释放时,会有警告信息。
Temp:函数内生命周期。

4.JOB之间的依赖关系

可以通过Job调度后得到的Jobhandle来管理JOB之间的顺序以及依赖关系。
当然也可以使用JobA.Complete之后,再调用JobB.Schedule来调度JobB。但是这样会导致线程切换回主线程,再调度JobB这样会有一个线程切换的开销。

最佳方式是JobB.Schedule(JobAHandle),这样就可以实现JobB在Job调度完成之后进行调度。(理解为Task的continueWith吧)

5.JOB Safety Checks

比较粗暴的检测JOB的之间的问题:
数据访问冲突(race condition)
数据访问越界
JOBS依赖关系(环形依赖等)
内存释放泄露

总结

JOB作为DOTS中重要的多线程工具,使用起来感觉相对简单易用。但其实多线程,能够用起来还是很多要注意的,稍不注意就有各种奇奇怪怪的问题。
个人之前很喜欢单线程开发,就因为简单,大脑想问题也简单,出错也容易找。多线程就麻烦多了,而且出错也难从断点找根源。希望JOBS这个工具,能解除这种恐惧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值