洪流学堂,让你快人几步。你好,我是跟着大智学Unity的萌新,我叫小新,最近在跟着大智学习DOTS。
Entities.ForEach是最常见也是最简单的遍历entity的方式,除此之外还有一些更灵活的方式在System中执行Job。这节咱们来看一下万金油Job.WithCode
。
使用Job.WithCode
SystemBase
类提供的Job.WithCode
可以通过lambda函数构造单个后台运行的job,这种方式非常简单。Job.WithCode
还可以在主线程上运行,并且还可以利用Burst编译来加快执行速度。
下面这个例子使用一个Job.WithCode
lambda函数,用随机数填充一个native数组,并使用另一个job将这些数字加在一起:
public class RandomSumJob : SystemBase
{
private uint seed = 1;
protected override void OnUpdate()
{
Random randomGen = new Random(seed++);
NativeArray<float> randomNumbers
= new NativeArray<float>(500, Allocator.TempJob);
Job.WithCode(() =>
{
for (int i = 0; i < randomNumbers.Length; i++)
{
randomNumbers[i] = randomGen.NextFloat();
}
}).Schedule();
// 要想获取job中的数据,必须使用NativeArray,即使只有一个值
NativeArray<float> result
= new NativeArray<float>(1, Allocator.TempJob);
Job.WithCode(() =>
{
for (int i = 0; i < randomNumbers.Length; i++)
{
result[0] += randomNumbers[i];
}
}).Schedule();
// 下面这句代码会立即完成已调度的job
// 但是性能更好的做法是在一帧的早些时候调度job
// 在一帧的晚些时候获取job的执行结果
this.CompleteDependency();
UnityEngine.Debug.Log("The sum of "
+ randomNumbers.Length + " numbers is " + result[0]);
randomNumbers.Dispose();
result.Dispose();
}
}
**注意:**要运行并行作业,需要实现IJobFor,然后可以在系统OnUpdate()中使用ScheduleParallel()方法进行调度。
捕获局部变量
你不能将参数传递给Job.WithCode的lambda函数或返回一个值。不过,你可以在OnUpdate()函数中捕获局部变量。
当你使用Schedule()
调度job时,还有以下额外的限制:
- 捕获的变量必须声明为NativeArray或者其他Native容器类型或blittable类型。
- 要返回数据,即使数据是单个值,也必须将返回值写入用于捕获数据的nativearray。(注意,使用
Run()
时,lambda是在主线程中执行,你可以写入任何捕获的变量。)
Job.WithCode
提供了一组方法,将只读和安全的属性捕获到native容器中。例如,你可以用WithReadOnly
表示不会更新容器,使用WithDisposeOnCompletion
在作业完成后自动释放容器。(Entities.ForEach提供了相同的功能。)
执行lambda函数
有两种方法来执行lambda函数:
Schedule()
-将函数作为单个非并行作业执行。作业在后台线程上运行代码,因此可以更好地利用可用的CPU资源。Run()
-立即在主线程上执行该函数。在大多数情况下,可以使用Burst.WithCode进行Burst编译,因此即使Job.WithCode仍在主线程上运行,代码执行也可以更快。
请注意,调用Run()
会自动完成Job.WithCode构造的所有依赖关系。如果未将JobHandle对象显式传递给Run()
,系统则假定当前Dependency属性表示函数的依赖关系。(如果函数没有依赖关系,可以传入new JobHandle)
依赖关系
默认情况下,系统使用Dependency属性管理与ECS相关的依赖关系。默认情况下,系统将按Entities.ForEach和Job.WithCode创建的每个作业在OnUpdate()函数中出现的顺序按它们添加到Dependency作业句柄中。你还可以通过将JobHandle传递给函数来手动管理作业依赖关系,然后返回结果依赖关系。
扩展阅读
【扩展学习】在洪流学堂公众号回复
DOTS
可以阅读本系列所有文章,更有视频教程等着你!
呼~ 今天小新絮絮叨叨的真是够够的了。没讲清楚的地方欢迎评论,咱们一起探索。
我是大智(vx:zhz11235),你的技术探路者,下次见!
别走!点赞,收藏哦!
好,你可以走了。