我们上次提到了DOTS在处理内存的时候是会根据每个entity里的Component区分为不同的Archetype,然后再存储在分配的chunk中,那么问题来了,当我修改了某个entity里面的Component,会发生什么呢?
structural changes
当我们修改了某个entity里面的Component的时候,会重新组织内存块或内存块内容的操作,这个操作被称为structural changes。
那么到底哪些时候会发生structural changes呢
- 添加或者删除Entity
- 添加或删除组件
- 设置shared component内的数值
添加或者删除Entity的时候,相当于 对chunk做了修改,导致需要对chunk里的数据重新排列或者对对应的Archetype添加新的chunk。
添加或删除组件的时候,相当于修改了这个Entity所在的Archetype,甚至会生成的新的Archetype,自然需要对对应的Archetype进行修改,重新排列。
而shared component就有一些特殊了,首先shared component的存储方式和普通的component不太一样,他会独立存储在外部,然后每个使用到该shared component的chunk会有一个指针指向存储位置,然后,当你生成或者修改shared component的时候,会先监测有没有完全相同的shared component存在,如果存在则不生成,我们上面说过了,每个chunk会有一个指针指向对应数值的shared component的存储位置,那当你的entity更改了他的shared component,那就代表当前chunk的shared component和他不同,就需要把他放到对应的chunk里,或者新建chunk进行存储,自然就会触发structural changes。
这个讲解shareComponent的视频还是很清楚直白的,贴到这
后果
当发生structural changes的时候,会发生Sync points,他会停掉你当前所有线程的工作,直到structural changes结束。因为structural changes会导致chunk的重新排布, 可能使已计划的其他作业失效。
解决
我们没办法完全避免structural changes发生,但是我们可以通过修改它的执行时间,让他在所有线程完成后,也就是帧的最后位置去执行,这样,我们的Sync points,就会从每次执行中断的多个,变成帧最后执行的一个。
方法就是通过使用 entity command buffers对需要进行的structural changes进行排队,然后在EntityCommandBufferSystem(每帧开始或最后执行)把所有的structural changes全部执行掉。