晚上好,我第一次在这里问一个问题,如果我犯了任何错误,请告诉我。
我和我的朋友最近开始编写一个基于组件的游戏引擎,并遇到了困扰我好几天的问题。 我有一个Entity类,它存储了附加到它的组件列表,我已经能够通过模板成功地向Entity添加和删除组件。简化代码如下所示:
class Component
{
type_index getType() { return std::type_index(typeid(*this)); }
template<class T>
bool Component::IsInheritedFrom(){
return std::is_base_of<T, std::remove_pointer<decltype(this)>>::value;
}
class Entity
{
std::vector<Component*> ComponentList;
template<class T>
T* getComponent(){
//Just iterate through the vector list and use each component's getType function to check
}
template<class T>
T* removeComponent(){
//Same as above
}
template<class T>
T* getBaseComponent(){
//Iterate and use component's IsInheritedFrom function to check
}
}
问题在于,在开发游戏时,我们创建了一些碰撞器组件,以及一个colliderManager:
class ColliderComponent : public Component
{
void CheckCollision(Entity* toCheck)
{
//Unable to get component
auto comp = toCheck->getBaseComponent<ColliderComponent>();
}
}
class SphericalColliderComponent : public ColliderComponent
{}
class AABBColliderComponent : public ColliderComponent
{}
对于具有球形或AABB对撞机的实体,IsInheritedFrom函数无法正常工作,因为继承的对撞机在向量列表中存储为Component *,因此当调用IsheritedFrom函数时,decltype读取(这个)作为Component *而不是AABBColliderComponent *。
我知道使用dynamic cast
肯定会起作用,但我并不是真的倾向于使用它,而是希望学习使用某些核心模板。我现在的解决方法是让每个组件类都有自己的类名作为字符串返回,并检查类名。
如果有人在正确的方向指导我,真的很感激,谢谢!而且还想知道我是否应该在gamedev部门发布这个。
答案 0 :(得分:1)
在运行时,您希望访问类型信息。
这意味着您需要一个RTTI系统。内置的通过动态强制转换和typeid公开。 Typeid不适合您的问题。
所以这意味着动态演员或推出自己的RTTI系统。
自己滚动的一种方法是维护要查询的所有类型的中央列表,然后使用模板和crtp填充vtable,其中包含有关给定对象的类型的信息。
另一个是完整的动态转换替换,其中每个类型都有足够的重新选择知识及其在类树中的位置,以填充您自己的手写rtti查询系统。
这些都是糟糕的想法,因为它类似于不知道如何驾驶汽车建议驾驶飞机前往杂货店的人。
最后一种方法是重新考虑您的设计。如果A是B并且与Bs一致地存储,则基于A而不是B的过滤是设计气味。考虑从类heirarchy中脱离的标签或某些内容来替换类型查询。