我想知道如何在C++中实现最快版本的实体组件系统(从现在开始的ECS).
首先,关于术语:
一个场景是一种用于容器的实体(和系统在某些实施方式中)
一个组件是一个简单的数据存储(如位置,碰撞盒,图像呈现等)
一个系统上执行的逻辑组件装配系统的要求(这可能是物理,玩家输入,简单渲染等)
一个实体包含多个组件来弥补最后的行为
我列出了我们在下面提出的所有设计.
场景包含所有无序的实体.
随着系统更新,每个系统都必须遍历所有实体并检查每个实体是否包含所有必需的组件,然后对这些实体执行更新.
显然,当拥有大量系统和/或许多实体时,这种方式并不太高效.
每个Component包含一个位掩码形式的类型标识符(例如1u << 5
/ binary [0...]100000
).然后,每个实体可以组成所有Component的类型标识符(假设所有typeID在Entity中都是唯一的),所以它看起来像
1u << 5 | 1u << 3 | 1u << 1
binary [0...]101010
场景包含某种类型的地图,系统可以轻松查找实体:
MovementSystem::update() {
for (auto& kv : parent_scene_) { // kv is pair>
if (kv.first & (POSITION | VELOCITY))
update_entities(kv.second); // update the whole set of fitting entities
}
}
优点:
比天真的方式更快
缺点:
系统必须在每次更新时都查找适当的实体.
位掩码(枚举)限制为多个位(32位uint32_t
,至少64位unsigned long long
),在某些情况下,您可能需要比位掩码允许的组件更多的组件.
Danvil在下面的答案中描述了这种方法.
优点:
完全摆脱位掩码的事情.
可能比设计#2更快.
缺点:
依赖dynamic_cast
于查找组件,而设计#2可以直接查找组件然后安全地查找组件static_cast
.
skypjack在下面的答案中描述了这种方法.他非常详细地解释了他的方法,所以我建议你阅读他的答案.