使用 Job.WithCode

使用 Job.WithCode

SystemBase提供Job.WithCode构造是一种将函数作为单个后台作业运行的简单方法。您还可以在主线程上运行Job.WithCode并仍然利用Burst编译来加速执行。

以下示例使用一个Job.WithCode lambda 函数用随机数填充本机数组,并使用另一个作业将这些数字相加:


public partial 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();

        // To get data out of a job, you must use a NativeArray
        // even if there is only one value
        NativeArray<float> result
            = new NativeArray<float>(1, Allocator.TempJob);

        Job.WithCode(() =>
        {
            for (int i = 0; i < randomNumbers.Length; i++)
            {
                result[0] += randomNumbers[i];
            }
        }).Schedule();

        // This completes the scheduled jobs to get the result immediately, but for
        // better efficiency you should schedule jobs early in the frame with one
        // system and get the results late in the frame with a different system.
        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()函数中捕获局部变量

当你计划你的工作在运行C#作业系统使用Schedule(),还有额外的限制:

  • 捕获的变量必须声明为 NativeArray —— 或其他本机容器—— 或blittable类型。
  • 要返回数据,您必须将返回值写入捕获的本机数组,即使数据是单个值。(请注意,您可以在使用Run().执行时写入任何捕获的变量。)

Job.WithCode提供了一组函数来将只读和安全属性应用于捕获的本机容器变量。例如,您可以使用WithReadOnly指定不更新容器并WithDisposeOnCompletion在作业完成后自动处置容器。Entities.ForEach提供相同的功能。)

有关这些修饰符和属性的更多信息,请参见Job.WithCode

执行函数

您有两个选项可以执行 lambda 函数:

  • Schedule()-- 将函数作为单个非并行作业执行。调度作业在后台线程上运行代码,因此可以更好地利用可用的 CPU 资源。
  • Run()-- 立即在主线程上执行函数。在大多数情况下,Job.WithCode可以被Burst编译,因此即使它仍然在主线程上运行,Job.WithCode 中执行代码也可以更快

注意调用会Run()自动完成Job.WithCode构造的所有依赖如果您没有显式地将JobHandle对象传递Run()系统,则假定当前的Dependency属性表示函数的依赖项。如果函数没有依赖项,传入一个新的JobHandle。)

依赖关系

默认情况下,系统使用其Dependency属性管理其与 ECS 相关的依赖项系统将使用Entities.ForEachJob.WithCode创建的每个作业按照它们在OnUpdate()函数中出现的顺序添加依赖作业句柄您还可以通过将JobHandle传递给您的函数手动管理作业依赖项,然后返回生成的依赖项。有关更多信息,请参阅依赖项Schedule

有关作业依赖项的更多一般信息,请参阅作业依赖项。

posted @ 2021-09-27 11:52  alps_01  阅读(64)  评论(0编辑  收藏  举报