所以我正在开发我的第一个游戏引擎而且我已经碰壁了。目前我有一个Entity基类,它有一个组件指针向量,它将保存指向某些系统管理器类(graphisManager,PhysicsManager等)中组件对象的指针。这是我当前的Entity标题(剥离以专注于主要问题):
Entity.h
class Component;
namespace BlazeGameWorld
{
class Entity
{
public:
BlazeFramework::Math::Vector2D position;
protected:
Vector<Component*> components;
static BlazeGraphics::GraphicsManager graphicsManager;
static BlazePhysics::PhysicsManager physicsManager;
static BlazeInput::InputManager inputManager;
//....other managers
private:
///////////////////////////////////////////////////////////////////////
public:
Entity();
~Entity();
virtual bool Initialize();
virtual bool Shutdown();
virtual void Update() = 0;
void AddComponent(Component* p_component);
//Part of the broadcast messaging system for components to be able
//to talk to one another in a decoupled way.
void SendMessage(uint messageID);
protected:
private:
};
}
正如您所看到的,我们的想法是拥有静态SystemManager类,它们将管理指向堆上实际组件的指针。这是一个潜在的PhysicsManager类的粗略Header(和其他Manager类类似):
PhysicsManager.h
class PhysicsComponent;
namespace BlazePhysics
{
class PhysicsManager
{
public:
protected:
int numPhysicsComponents;
private:
Vector<PhysicsComponent*> physicsComponents;
/////////////////////////////////////////////////////////////
public:
PhysicsManager();
~PhysicsManager();
bool Initialize();
bool Shutdown();
void Update();
template <typename PhysicsComponentType>
PhysicsComponentType* CreatePhysicsComponent();
private:
};
//template definitions
template <typename PhysicsComponentType>
PhysicsComponentType* PhysicsManager::CreatePhysicsComponent()
{
PhysicsComponentType* physicsComponent = new PhysicsComponentType
physicsComponents.push_back(physicsComponent);
return physicsComponents.at(numPhysicsComponents++);
}
}
所以我可以在PhysicsManger向量中存储所有不同的physicsComponent指针(指向CollisionComponents,PositionComponents等)。问题是如果我想调用特定物理组件的方法,我无法编译。例如,如果(在PhysicsManager的更新循环中)我想更新一个collisionComponent的CheckCollision()方法,每个帧我不能只在for循环physicsComponents.at(i).CheckCollision
中说,因为编译器在编译时不知道什么一个CollisionComponent是。有没有办法可以首先推断出数组中组件的类型,然后如果匹配CollisionComponent则调用CheckCollision方法?或者有更好的实现这个,因为这似乎有点笨重?
答案 0 :(得分:2)
实体不应该了解您的系统,它们应该只是一个组件集合。否则引入另一个引擎系统的过程也需要改变实体类,这违背了ECS的整个目的。
系统也不应该管理组件。一个系统可以使用几个组件,并且许多系统可以使用,例位置/碰撞几何组件。
所以,在我看来:
这样,例如,如果要为某些实体添加脚本行为,您只需添加ScriptComponent
和ScriptingSystem
即可。您现有的所有代码都不需要任何更改。
This question在这个主题上有很多非常有用的资源。