我想实现实体组件系统,其中每个实体都有一个组件列表。每个组件都派生自 BaseComponent 类。实体中的每个组件都是唯一的 - 例如,实体不可能有两个 TransformComponent 组件。我想使用方法getComponent():
快速和类型安全地访问实体中的组件template <typename T>
T * getComponent();
在实体中实现组件容器的最佳方法是什么?
PS:我有很多实体(大约10-20万),每个实体有大约2-3个组件,10个是最大组件。所以我担心 unordered_map 对我的任务来说太重了。
答案 0 :(得分:1)
我建议将元组方法作为一个稻草人,以确定您的其他要求是什么:
#include <utility>
template <typename...Components>
class Entity : private Components... {
public:
Entity() = default;
Entity(Components...components) :
Components(std::move(components))... {}
template <typename T>
T& get() {
return *this;
}
template <typename T>
const T& get() const {
return *this;
}
};
#include <iostream>
struct ComponentA { void f() const { std::cout << "I'm a ComponentA\n"; } };
struct ComponentB { void f() const { std::cout << "I'm a ComponentB\n"; } };
struct ComponentC { void f() const { std::cout << "I'm a ComponentC\n"; } };
int main() {
{
Entity<ComponentA, ComponentB, ComponentC> e;
e.get<ComponentC>().f();
e.get<ComponentB>().f();
e.get<ComponentA>().f();
}
{
ComponentA a;
Entity<ComponentA, ComponentB> e{a, {}};
}
{
// error: duplicate base type
// Entity<ComponentA, ComponentA> invalid_entity;
}
}
它的优点是所有类型都是具体的,Component
类型甚至不需要相关。
答案 1 :(得分:0)
我决定使用简单方法在 Entity 中包含数组* BaseComponent m_comps [MAX_COMPONENTS] ,并为每个组件类型分配唯一ID。因为组件类型的数量限制为20-30。通过这种方式,我可以最快地访问组件,只需要在实体内部存储20-30个指针(并且它们将分配在一个块中,实体本身允许良好的缓存局部性)
我使用此代码进行类型安全访问:
template <typename T>
T * Entity::getComp()
{
return (T*)m_comps[T::idCompType];
}
并且每个组件都应该声明const静态成员 idCompType