【发布时间】:2015-10-29 09:47:45
【问题描述】:
我正在尝试在游戏引擎项目上实现基于组件的架构。每个 GameObject 都有一个 unordered_map,它包含一个指向 Component 基类的指针。此时,我只有一个组件派生类,即Transform 类。我想实现这个类似于 Unity 约定的基于组件的架构:我想通过调用像 GetComponent<Transform>() 这样的成员模板函数来获取游戏对象的组件。
这是标题:
Component.h
enum type{
TRANSFORM // more will be added later
};
class Component // base class
{
public:
Component() : _owner(NULL) {}
virtual ~Component(){}
static type Type;
protected:
GameObject* _owner;
};
Transform.h
class Transform : public Component
{
public:
Transform();
~Transform();
static type Type;
void Rotate(float deg);
// to be encapsulated later on
Vector2D _position;
float _rotation;
Vector2D _scale;
};
GameObject.h
class GameObject
{
public:
GameObject();
~GameObject();
void Update();
//and more member functions
template<class T>
T* GetComponent();
private:
// some more private members
unordered_map<type, Component*> _componentList; // only 1 component of each type
};
template<class T>
T* GameObject::GetComponent()
{
return static_cast<T*>(_componentList[T::Type]);
}
我的初始实现使用std::vector 来保持Component* 并且应用程序以60 fps 运行(我还有一个帧速率控制器,它只是将FPS 限制为60)。当我更改为 unordered_map 来访问这些组件指针时,性能下降到 15 FPS。
我只画了两个四边形,此时我每帧只调用了 6 次GetComponent<Transform>(),所以场景中没有发生太多事情。
我尝试了什么?
我尝试使用 const char*、std::string、type_info 和最后的 enum type 作为 unordered_map 的键值,但没有任何帮助:所有实现都让我达到了 15-16 FPS。
是什么导致了这个性能问题?如何隔离问题?
我希望我提供了足够的细节,如有需要,请随时索取更多代码
【问题讨论】:
-
实体通常只有很少的组件,可能是 5 个或最多 30 个。对于 30 个元素,具有线性搜索的向量优于 hash_map。我会坚持使用向量。
-
我对游戏编程一无所知,但你不能用总是 num_components 个元素来实例化一个指针数组吗?类型枚举值可以作为索引转换到数组中,如果你的组件很少,它可能不是很高的内存开销
-
你还改变了什么?我不相信您仅更改了组件的存储容器。计算哈希值很简单。低于向 GPU 发送绘制指令的成本。
-
@RichardHodges 说真的,我几乎没有任何组件。我只是更改容器类型。如果我只是通过更改 GameObject.h 和 GameObject.cpp 再次将其恢复为
vector(在构造函数中,我只需将一个 Transform 组件添加到容器中://_componentList.push_back(new Transform());到_componentList.emplace(Transform::Type, new Transform());) -
如果你说的是真的,我想你需要分析它,看看发生了什么。错误不会在标准库中。另请注意,看在上帝的份上,请将指针存储在带有 unique_ptr 或 shared_ptr 的映射/向量中。看到容器中的原始指针让每个人都很难过:(
标签: c++ performance templates inheritance unordered-map