Unity DOTS系列之IJobChunk来迭代处理数据

devtools/2024/10/19 21:32:57/

最近DOTS发布了正式的版本, 我们来分享一下System中如何在System中使用IJobChunk来迭代处理World中的数据,方便大家上手学习掌握Unity DOTS开发。

再回顾一次基于ArcheType Chunk内存管理

我们先再次回顾以下基于ArcheType的Chunk内存管理。每一类Entity都是由一些列的ComponentData组合而成的,这个组合我们使用ArcheType来进行描述。同一种ArcheType的Entity具有相通的内存大小与布局,存放在chunk里面。每个chunk只会存放同一种ArcheType类型的Entity的组件数据。每个chunk的大小是16kb。里面并排存放着每个Entity的组件数据。如下所示:

===============================

ArchType1:

chunk1【e1(c1c2),e2(c1c2),e3(c1c2)】

chunk2【e4(c1c2),e5(c1c2),e6(c1c2)】

...

======================

ArchType2:

chunk1【e1(c3c4),e2(c3c4),e3(c3c4)】

chunk2【e4(c3c4),e5(c3c4),e6(c3c4)】

...

===============================

ArchType3:

chunk1【e1(c5c6),e2(c5c6),e3(c5c6)】

chunk2【e3(c5c6),e4(c5c6),e5(c5c6)】

...

===============================

使用IjobChunk的主要流程

在DOTS中迭代处理Entity的组件数据先找到对应符合条件的ArcheType,然后再找到ArcheType对应的所有的Chunks,再遍历每个Chunk里面的每个Entity的组件数据。有了这个思路以后,我们先来看下如何来使用IJobChunk机制来进行数据迭代。步骤如下:

  1: 定义一个EntityQuery对象,它根据赛选条件而生成,当IJobChunk来筛选Entity的时候就基于这个对象的筛选条件。EntityQuery对象是基于EntityQueryBuilder对象创建出来。EntityQueryBuilder负责将筛选条件转成最后的EntityQuery对象。示例代码如下:

    public partial class UpdateTranslationFromVelocitySystem : SystemBase

    {

        EntityQuery query;

        protected override void OnCreate()

        {

            // Set up the query

            query = new EntityQueryBuilder(Allocator.Temp)

                .WithAllRW<ObjectPosition>()

                .WithAll<VelocityVector>()

                .Build(this);

        }

  2: 定义一个继承IJobChunk接口的Job结构体,并实现Execute接口。

public struct UpdateTranslationFromVelocityJob : IJobChunk {

public void Execute(in ArchetypeChunk chunk, 

int unfilteredChunkIndex, 

bool useEnabledMask, 

in v128 chunkEnabledMask)

}

  3:定义在Job中Execute中所使用的数据,这些数据在System Update迭代的时候传入。IJobChunk迭代处理数据的时候都是一个一个Chunk来处理的,每个Chunk调用一次Execute函数。在Execute函数中你需要什么样的数据就可以定义在Job的结构体里面。

public struct UpdateTranslationFromVelocityJob : IJobChunk

    {

        public ComponentTypeHandle<VelocityVector> VelocityTypeHandle;

        public ComponentTypeHandle<ObjectPosition> PositionTypeHandle;

        public float DeltaTime;      

 

public void Execute(in ArchetypeChunk chunk, 

int unfilteredChunkIndex, 

bool useEnabledMask, 

in v128 chunkEnabledMask)

        {

        }

    }

利用ComponentTypeHandle可以把chunk内存块里面所有的对应的组件的数据放到NativeArray里面给Execute迭代使用。普通的数据可以直接定义即可。

  4: 实现Interface IjobChunk的Execute函数的具体迭代逻辑,用于具体的处理。处理组件数据的时候,基于ComponentTypeHandle把Chunk里面的组件数据获取到一个NativeArray里面。Execute有4个参数,

     chunk,类型是ArcheTypeChunk,就是我们的chunk内存块,存放数据地方;

   unfilteredChunkIndex: 我们当前chunk,所在所有chunk的索引;

   bool useEnbaleMask,  in v128 chunkEnableMask, 是enableable component的bitmap,给我们查询使用。

在Execute里面我们使用ChunkEntityEnumerator来遍历chunk里面的每个entity的Component,参考代码如下:

NativeArray<VelocityVector> velocityVectors = chunk.GetNativeArray(ref VelocityTypeHandle);

            NativeArray<ObjectPosition> translations = chunk.GetNativeArray(ref PositionTypeHandle);

            var enumerator = new ChunkEntityEnumerator(useEnabledMask, chunkEnabledMask, chunk.Count);

            while(enumerator.NextEntityIndex(out var i))

            {

                float3 translation = translations[i].Value;

                float3 velocity = velocityVectors[i].Value;

                float3 newTranslation = translation + velocity * DeltaTime;

                translations[i] = new ObjectPosition() { Value = newTranslation };

            }

  5: 在System中来使用IJobChunk,进行执行。当JobChunk的结构体定义好以后,我们就可以在System中使用它们,在System的Update中定义一个结构体对象,把JobChunk结构体中的数据初始化好,然后调用JobChunk的执行函数。执行函数有三个接口,分别如下:

  Run: 执行当前的job(job chunk 的execute)是在当前线程(system的update迭代所在的线程);

  Shedule: 就是会在另外一个线程来处理我们的Excute,按照顺序一个一个来处理;  chunk1, chunk2, chunk3….

SheduleParallel: 并发处理, 可以多个线程同时并发处理多个chunk,   线程1 chunk1, 线程2 处理chunk2 , …..

按照这5个步骤,来定义与使用IJobChunk来计算迭代游戏逻辑与数据。

今天的分享就到这里,关注我们获取更多的DOTS的相关资料


http://www.ppmy.cn/devtools/117725.html

相关文章

【rust】 基于rust编写wasm,实现markdown转换为html文本

文章目录 背景转换预览核心代码前置依赖rustup换源cargo换源中科大 wasm-pack安装 背景 尝试用rust编写一款markdown转html的插件&#xff0c;通过wasm给html使用&#xff0c;不得不说体积挺小&#xff0c;约200K&#xff0c; 比go的wasm起步2MB看着舒服点。 不过go的配置和换…

计算机毕业设计之:云中e百货微信小程序设计与实现(源码+文档+定制)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

Leetcode面试经典150题-322.零钱兑换

给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1 。 你可以认为每种硬币的数量是无限的。 示…

io流(学习笔记02)采用递归方式寻找文件

方法递归&#xff08;为了遍历一个文件夹内的所有文件夹&#xff0c;包括子文件夹内部的文件...&#xff09; 递归是一种算法 形式上&#xff1a;方法调用自身的形式 递归的形式&#xff1a; 直接递归&#xff1a;方法自己调用自己。 间接递归&#xff1a;方法调用其他方法…

Pandas 总结试卷

Pandas 总结试卷 # 导入pandas库 import pandas as pd# 0. 创建一个空的DataFrame df pd.DataFrame() df# 创建一个包含学生姓名、年龄、成绩的DataFrame # 数据表为&#xff1a;姓名 年龄 成绩 张三 18 85 李四 19 90 王五 20 78 赵六 21 92 data {姓名: [张三, 李四, 王五…

Python办公自动化案例:将Excel数据批量保存到Word表格中

案例:将excel数据批量保存到Word表格中 要将Excel数据批量保存到Word表格中,可以使用Python的openpyxl库来读取Excel文件,以及python-docx库来创建和编辑Word文档。以下是一段示例代码,以及代码解释和一些注意事项。 准备好的Excel数据: 1.安装所需库 首先,确保你已经…

JAVA集成Jasypt进行加密、解密(SpringBoot)

JAVA (SpringBoot) 集成 Jasypt 进行加密、解密 - 详细教程 在开发过程中&#xff0c;我们经常需要处理敏感数据&#xff0c;如数据库密码、API 密钥等。为了确保这些数据的安全性&#xff0c;我们可以使用加密技术来保护它们不被泄露。Jasypt&#xff08;Java Simplified Enc…

【C高级】有关shell脚本的一些练习

目录 1、写一个shell脚本&#xff0c;将以下内容放到脚本中&#xff1a; 2、写一个脚本&#xff0c;包含以下内容&#xff1a; 1、写一个shell脚本&#xff0c;将以下内容放到脚本中&#xff1a; 1、在家目录下创建目录文件&#xff0c;dir 2、dir下创建dir1和dir2 …