IJobEntity后是IJobChunk
IJobChunk
要了解IJobChunk首先我们得先了解下Chunk以及ECS的内存管理机制
Chunk
chunk就是最小内存块,IJobChunk的执行单位就是chunk,而ECS机制会根据每个entity下的componet的不同,定义成多个不同的archetype,比如EntityA 下有ComponentA,定义为ArchetypeA,
EntityB 下有ComponentB,定义为ArchetypeB, EntityC 下A有ComponentA 和 ComponentB, 定义为ArchetypeC, 如果有个 新的 EntityD 下有ComponentB ,那么就会归到 ArchetypeB下。然后,每个Archetype会分配一到多个chunk用来存储数据,这样的好处是,在处理多个相同类型的数据时候,他们命中的都是同一个的chunk,减少内存的读取和释放频率。上面也说了IJobChunk是以chunk为执行单位的,这和IJobEntity这种以Entity为单位做操作的相对更加节省内存的读取和释放频率。
IJobChunk使用
在DOTS中迭代处理Entity的组件数据先找到对应符合条件的ArcheType,然后再找到ArcheType对应的所有的Chunks,再遍历每个Chunk里面的每个Entity的组件数据。有了这个思路以后,我们先来看下如何来使用IJobChunk机制来进行数据迭代。
首先声明一个
这里的Execute和JobEntity类似都是必须声明的,不同的是参数不同。
public struct UpdateTranslationFromVelocityJob : IJobChunk
{
public ComponentTypeHandle<VelocityVector> VelocityTypeHandle;
public ComponentTypeHandle<ObjectPosition> PositionTypeHandle;
public float DeltaTime;
[BurstCompile]
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{
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 };
}
}
}
然后是调用
这个跟JobEntity也类似,有ScheduleParallel 和Run这些调用方法
protected override void OnUpdate()
{
// Instantiate the job struct
var updateFromVelocityJob
= new UpdateTranslationFromVelocityJob();
// Set the job component type handles
// "this" is your SystemBase subclass
updateFromVelocityJob.PositionTypeHandle
= this.GetComponentTypeHandle<ObjectPosition>(false);
updateFromVelocityJob.VelocityTypeHandle
= this.GetComponentTypeHandle<VelocityVector>(true);
// Set other data need in job, such as time
updateFromVelocityJob.DeltaTime = World.Time.DeltaTime;
// Schedule the job
this.Dependency
= updateFromVelocityJob.ScheduleParallel(query, this.Dependency);
}