ECS概念
核心思想:Data-Oriented Tech Stack,不同于传统的Object-Oriented方式。
E:entities
C:components——data
S:systems——behaviour
上图中System读取Translation和Roation,让后将运算结果更新到LocalToWorld component。所以一个System是和一组Componets绑定的,只要拥有这个组合的Entity,这个System都会更新其数据(component)。
Archetypes:原型,表示一个唯一的components的组合叫做一个原型。
上图中EntityA和EntityB属于一个原型,EntityC属于另一个原型。
内存结构:ECS以chunks为单位分配内存,每个对应一个ArchetypeChunk。
ArchetypeChunk:原型块
拥有相同Archetype的Entities的所有Components存放在同一块unmanaged memory里,这个非托管的内存块就叫ArchtypeChunk。
如果enitty的archetype变化了(增删components),它的components的存储chunk也会变化。
archetye和chunk的关系:一对多。
可以根据archetype就能找到所有有用这个components组合的entities,效率高,因为archetypes的数量有限。如果直接遍历所有entities则数据量就非常大了。
chunk位置更新算法:
(1)chunk始终保持紧密排列,无序
(2)entity创建或增删components时,它会被放置在其archetype对应的第一个有空位的的chunk里面
(3)当一个entity从archetype中移除时,首先会在chunk中移除该enity对应的components,然后将chunk中最后一个entity移到这个空位填充,保持紧密排列
shared components共享组件规则:
(1)共享组件的值会影响entities存储的chunk
(2)同一个chunk中的shared components的values一定一样
(3)如果修改一个entity的shared component的value,会导致这个entity移动到别的chunk
(4)移动的时候,有可能需要创建新的chunk
(5)尽量使用shared components,因为它的性能更高,eg:RenderMesh component
Entity查询:EntityQuery
根据components需求获取所有满足该需求的entities列表。
一次query会返回一个满足需求的chunks列表。然后可以使用IJobChunk来访问这些components数据,或者使用IJobForEach或 non-Job for-each loop。
注意:IJobForEach隐式创建一个entity query。
Jobs:JobComponentSystem
为了充分利用Job System,ECS提供了JobComponentSystem,以及Job类型IJobForEACH和IJobChunk,用来在main thread外处理数据。
IJobForEach/IJobForEachwithEntity通常是用起来最简单的。
IJobChunk可以用来处理IJobForEach处理不了的复杂情况。
这些ECS Jobs使用一了个EntityQuery对象,不只是用来标记需要的components组合,而且可以指定需要的component的read-only或read-write状态。这个访问标记决定了Job scheduler在以什么方式来调度job:
(1)read-only的job可以run in parallel;
(2)write的job当有其他job在访问同样的数据时则是run in sequence。
System组织形式:World和group
ECS提供World和group来组织systems。
默认情况下,ECS会创建一个default World和一组预定义的groups,然后它会找到所有的systems,实例化以后添加到预定义的simulation group里。
你可以指定一个group内部不同systems update的时序。
group本身也是一个system,所以可以将一个group添加到另一个group,并指定其update顺序。
一个group里面的所有systems会在下一个system或group之前update。
如果不指定update order,一组systems始终会以不依赖于创建时序的某种特定顺序执行。也就是说同样一组systems,它的执行顺序一定是确定的,不存在随机性。
System的update在main thread执行。但system可以使用job让任务运行在worker thread。