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

最近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迭代使用。普通的数据可以直接定义即可。

  1. 实现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 };
            }
  1. 在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来计算迭代游戏逻辑与数据。

相关推荐
虾球xz38 分钟前
CppCon 2015 学习:3D Face Tracking and Reconstruction using Modern C++
开发语言·c++·学习·3d
JoannaJuanCV41 分钟前
BEV和OCC学习-3:mmdet3d 坐标系
3d·occ·bev
lingling0091 小时前
3D视觉重构工业智造:解码迁移科技如何用“硬核之眼“重塑生产节拍
科技·3d·重构
Shan12052 小时前
3Ds Max 2026安装包+教程网盘下载与安装教程指南
数学建模·3d
时间之里2 小时前
【图像处理3D】:世界坐标系
图像处理·数码相机·3d
从零开始学习人工智能3 小时前
从游戏到自动驾驶:互联网时代强化学习如何让机器学会自主决策?
人工智能·游戏·自动驾驶
心之所向,自强不息3 小时前
【Unity Shader编程】之让画面动起来
unity·游戏引擎
渲吧云渲染6 小时前
3ds Max 渲染技术突破:一键解锁照片级真实感!
3d
Tiffany_Ho6 小时前
【threejs】每天一个小案例讲解:创建基本的3D场景
3d·three
豆沙沙包?15 小时前
2025年- H77-Lc185--45.跳跃游戏II(贪心)--Java版
java·开发语言·游戏