Unity探路营

在ECS系统中使用Job.WithCode

2020-12-03  本文已影响0人  洪智

洪流学堂,让你快人几步。你好,我是跟着大智学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时,还有以下额外的限制:

Job.WithCode提供了一组方法,将只读和安全的属性捕获到native容器中。例如,你可以用WithReadOnly表示不会更新容器,使用WithDisposeOnCompletion在作业完成后自动释放容器。(Entities.ForEach提供了相同的功能。)

执行lambda函数

有两种方法来执行lambda函数:

请注意,调用Run()会自动完成Job.WithCode构造的所有依赖关系。如果未将JobHandle对象显式传递给Run(),系统则假定当前Dependency属性表示函数的依赖关系。(如果函数没有依赖关系,可以传入new JobHandle)

依赖关系

默认情况下,系统使用Dependency属性管理与ECS相关的依赖关系。默认情况下,系统将按Entities.ForEach和Job.WithCode创建的每个作业在OnUpdate()函数中出现的顺序按它们添加到Dependency作业句柄中。你还可以通过将JobHandle传递给函数来手动管理作业依赖关系,然后返回结果依赖关系。

扩展阅读

【扩展学习】洪流学堂回复DOTS可以阅读本系列所有文章,更有视频教程等着你!


呼~ 今天小新絮絮叨叨的真是够够的了。没讲清楚的地方欢迎评论,咱们一起探索。

我是大智,你的技术探路者,下次见!

别走!点赞收藏哦!

好,你可以走了。

上一篇 下一篇

猜你喜欢

热点阅读