ECS / CES 共享和依赖组件和缓存位置
ECS / CES shared and dependent components and cache locality
当存在共享或依赖的组件时,我一直在努力思考 ECS 的工作原理。我已经阅读了大量关于 ECS 的文章,但似乎无法找到明确的答案。
假设以下场景:
我有一个实体,它有一个 ModelComponent(或 MeshComponent)、一个 PositionComponent 和一个 ParticlesComponent(或 EmitterComponent)。
ModelRenderSystem 需要 ModelComponent 和 PositionComponent。
ParticleRenderSystem 需要 ParticlesComponent 和 PositionComponent。
在 ModelRenderSystem 中,为了缓存效率/局部性,我想 运行 通过紧凑数组中的所有 ModelComponents 并渲染它们,但是对于每个模型,我需要拉 PositionComponent。我什至还没有开始考虑如何处理每个模型的纹理、着色器等(这肯定会破坏缓存)。
ParticleRenderSystem 存在类似问题。我需要 ParticlesComponent 和 PositionComponent,我希望能够运行 以缓存高效/友好的方式通过所有 ParticlesComponent。
我考虑过让 ModelComponent 和 ParticlesComponent 各有自己的位置,但每次模型位置改变时都需要同步它们(想象角色上的粒子效果)。这添加了另一个需要跟踪和同步组件或值的实体或组件(并可能否定任何缓存效率)。
其他人如何处理此类依赖性问题?
降低复杂性的一种方法是反转数据流。
请考虑您的 ModelRenderSystem
有一个侦听器回调,允许 entity framework 通知它一个实体已添加到包含位置和模型组件的模拟中。在此回调期间,系统可以在位置组件或拥有该组件的系统上注册一个回调,允许 ModelRenderSystem
在该位置对象更改时得到通知。
随着来自位置变化的变化事件的到来,ModelRenderSystem
可以排队它必须在更新阶段复制的修改列表,然后在更新期间,它真的是一个简单的查找每个修改模型和将位置设置为事件中的值。
好处是,对于每一帧,您只会复制在帧期间实际发生变化的位置变化,并且可以最大限度地减少复制数据所需的查找。虽然位置更新传播到各种感兴趣的系统可能不那么缓存友好,但您观察到的收益超过了这一点。
最后,不要忘记系统不一定需要迭代组件。实体系统中的组件允许您轻松切换可插入行为。系统始终可以管理对缓存更友好的数据结构,并使用上述回调方法,让您可以做到这一点,并以最小的耦合超级轻松地管理数据复制。
当存在共享或依赖的组件时,我一直在努力思考 ECS 的工作原理。我已经阅读了大量关于 ECS 的文章,但似乎无法找到明确的答案。
假设以下场景:
我有一个实体,它有一个 ModelComponent(或 MeshComponent)、一个 PositionComponent 和一个 ParticlesComponent(或 EmitterComponent)。
ModelRenderSystem 需要 ModelComponent 和 PositionComponent。
ParticleRenderSystem 需要 ParticlesComponent 和 PositionComponent。
在 ModelRenderSystem 中,为了缓存效率/局部性,我想 运行 通过紧凑数组中的所有 ModelComponents 并渲染它们,但是对于每个模型,我需要拉 PositionComponent。我什至还没有开始考虑如何处理每个模型的纹理、着色器等(这肯定会破坏缓存)。
ParticleRenderSystem 存在类似问题。我需要 ParticlesComponent 和 PositionComponent,我希望能够运行 以缓存高效/友好的方式通过所有 ParticlesComponent。
我考虑过让 ModelComponent 和 ParticlesComponent 各有自己的位置,但每次模型位置改变时都需要同步它们(想象角色上的粒子效果)。这添加了另一个需要跟踪和同步组件或值的实体或组件(并可能否定任何缓存效率)。
其他人如何处理此类依赖性问题?
降低复杂性的一种方法是反转数据流。
请考虑您的 ModelRenderSystem
有一个侦听器回调,允许 entity framework 通知它一个实体已添加到包含位置和模型组件的模拟中。在此回调期间,系统可以在位置组件或拥有该组件的系统上注册一个回调,允许 ModelRenderSystem
在该位置对象更改时得到通知。
随着来自位置变化的变化事件的到来,ModelRenderSystem
可以排队它必须在更新阶段复制的修改列表,然后在更新期间,它真的是一个简单的查找每个修改模型和将位置设置为事件中的值。
好处是,对于每一帧,您只会复制在帧期间实际发生变化的位置变化,并且可以最大限度地减少复制数据所需的查找。虽然位置更新传播到各种感兴趣的系统可能不那么缓存友好,但您观察到的收益超过了这一点。
最后,不要忘记系统不一定需要迭代组件。实体系统中的组件允许您轻松切换可插入行为。系统始终可以管理对缓存更友好的数据结构,并使用上述回调方法,让您可以做到这一点,并以最小的耦合超级轻松地管理数据复制。