C++:设计基于组件的实体系统——高级问题
Posted
技术标签:
【中文标题】C++:设计基于组件的实体系统——高级问题【英文标题】:C++: Designing a component-based entity system - advanced problems 【发布时间】:2011-07-04 09:51:02 【问题描述】:在我用 C++ 编写的游戏引擎中,我已经摆脱了经典的分层实体系统并构建了一个基于组件的实体系统。它大致是这样工作的:
实体只是组件的容器。一些示例组件包括:Point、Sprite、Physics、Emitter。
每个实体最多可以包含每种类型的一个组件。某些组件依赖于另一个组件,例如 Physics 和 Sprite 依赖于 Point,因为它们需要由它传递的位置和角度。
所以组件系统一切正常,但现在我无法实现更专业的实体,例如:
相机,需要额外的功能来处理移动和缩放 需要支持才能接收用户输入并移动的玩家现在,我可以通过继承轻松解决这个问题。只需从实体派生相机并添加其他缩放功能和成员。但这只是感觉不对。
我的问题:
如何使用 C++ 中的组件系统解决专门实体的问题?【问题讨论】:
将相机和玩家变成实体有什么好处?为什么它们不应该是它们自己的东西,它们本来就是古怪的东西呢?我注意到您对“播放器”的描述实际上只是 MVC 的控制器端,并且不适用于其他播放器(如果存在)。我的主要观点是:不要创建一个创新系统,只是为了让它成为一个阻止你在独特案例上做正确事情的球和链条。 @Mike:我希望我的实体系统是统一的。相机基本上无非是一个有位置的实体,我发现这样做是合乎逻辑的,也是正确的做法。玩家也一样,仅此而已,玩家拥有物理实体的所有典型属性。 难道你不能像为其他独特功能一样为播放器和相机制作新的组件类型吗? @Jay:不,但相机和玩家对我来说绝对是实体,它们是存在于世界空间中的对象。 我认为将玩家的游戏内表示(这是一个物理实体)与玩家本身(世界的控制器)分开是一个好主意。同样,您可以将相机作为实体(在世界上具有位置)与对该相机的解释(渲染缩放等)分开。 【参考方案1】:如何给每个实体一些限制,限制它可以拥有什么样的组件(也许还有它应该拥有什么),并在你从该实体派生时放宽这些限制。例如通过添加一个虚函数来验证是否可以将某个组件添加到实体中。
【讨论】:
【参考方案2】:您似乎怀疑这里的 IS-A 关系。那么为什么不让它成为HAS-A关系呢?相机和玩家可以不是实体,而是具有实体(或对实体的引用)但存在于组件系统之外的对象。这样,您可以轻松地保持组件系统的一致性和正交性。
这也很符合这两个示例(相机/播放器)作为“胶水”对象的含义。玩家将实体系统粘合到输入系统并充当控制器。相机将实体系统粘合到渲染器上并充当一种观察者。
【讨论】:
【参考方案3】:一个常见的解决方案是使用访问者模式。基本上,您的实体将被访问者类“访问”。在您的实体内部,您将拥有:
void onVisitTime(Visitor* v)
// for each myComponent...
v->visit(myComponent);
// end for each
然后,您将在访问者类中:
void visit(PointComponent* p);
void visit(CameraComponent* c);
请注意,这有点违反 OOP(数据操作在对象外部处理,因为访问者会处理它)。而且访问者往往会变得过于复杂,所以这不是一个很好的解决方案。
【讨论】:
我不明白访问者模式在这里有什么帮助。这是一种动态的类型调度机制。 OP 询问如何设计他的系统。我不明白它有什么关系。 它简化了实体的专业化:例如,他可以只添加一个 ZoomCameraComponent,而不涉及类层次结构。但我可能误解了这个问题。【参考方案4】:基于组件的系统通常具有允许向实体发送“消息”的通用方法,例如函数send(string message_type, void* data)
。然后实体将它传递给它的所有组件,只有其中一些组件会对它做出反应。例如,您的组件Point
可以对send("move", &direction)
做出反应。或者您可以引入moveable
组件以获得更多控制权。你的相机也一样,添加一个组件view
并让它处理“缩放”消息。
这种模块化设计已经允许定义不同类型的相机(例如没有moveable
组件的固定相机),将某些组件重用于其他东西(另一种类型的实体可能使用“视图”),您还可以通过让各种组件以不同方式处理每条消息来获得灵活性。
当然,可能需要一些优化技巧,尤其是对于经常使用的消息。
【讨论】:
【参考方案5】:如果只创建支持该行为的组件呢?例如,一个 InputComponent 可以处理来自玩家的输入。然后你的设计保持不变,玩家只是一个实体,它允许从键盘输入,而不是从 AI 控制器输入。
【讨论】:
以上是关于C++:设计基于组件的实体系统——高级问题的主要内容,如果未能解决你的问题,请参考以下文章