C++;:设计基于组件的实体系统-高级问题 我的游戏引擎,是用C++编写的,我已经离开了经典的层次实体系统,并建立了基于组件的系统。它大致是这样工作的:
实体仅仅是组件的容器。一些示例组件包括:点、精灵、物理、发射器 每个实体最多可以容纳每种类型的一个组件。有些组件依赖于另一个组件,比如物理和精灵依赖于点,因为它们需要一个由点传递的位置和角度 因此,组件系统的一切都很好,但现在我在实现更专业的实体时遇到了困难,例如:C++;:设计基于组件的实体系统-高级问题 我的游戏引擎,是用C++编写的,我已经离开了经典的层次实体系统,并建立了基于组件的系统。它大致是这样工作的:,c++,components,entities,C++,Components,Entities,实体仅仅是组件的容器。一些示例组件包括:点、精灵、物理、发射器 每个实体最多可以容纳每种类型的一个组件。有些组件依赖于另一个组件,比如物理和精灵依赖于点,因为它们需要一个由点传递的位置和角度 因此,组件系统的一切都很好,但现在我在实现更专业的实体时遇到了困难,例如: 照相机,需要额外的功能来处理移动和变焦 一个播放器,需要支持才能接收用户输入并移动 现在,我可以很容易地用继承来解决这个问题。只需从实体派生摄影机并添加其他缩放功能和成员。但这感觉很不对 我的问题: 如何解决C++中的构件实体
- 照相机,需要额外的功能来处理移动和变焦
- 一个播放器,需要支持才能接收用户输入并移动
-
如何解决C++中的构件实体问题——
这也非常符合这两个示例(摄影机/播放器)作为“粘合”对象的含义。玩家将实体系统粘在输入系统上,并充当控制器。摄影机将实体系统粘在渲染器上,并充当一种观察者。常见的解决方案是使用访问者模式。基本上,您的实体将被访问者类“访问”。在实体内部,您将拥有:
void onVisitTime(Visitor* v)
{
// for each myComponent...
v->visit(myComponent);
// end for each
}
然后,在Visitor类中:
void visit(PointComponent* p);
void visit(CameraComponent* c);
请注意,这有点违反OOP(数据操作在对象外部处理,因为访问者将处理它)。而且访问者往往变得过于复杂,所以这不是一个很好的解决方案。基于组件的系统通常有一种通用方法,允许向实体发送“消息”,比如函数
send(字符串消息类型,void*data)
。实体然后将其传递给其所有组件,只有其中一些组件会对其作出反应。例如,您的组件点
可以对发送(“移动”和方向)
做出反应。或者您可以引入一个可移动的
组件以获得更多控制。对于您的相机,添加一个组件视图
,并使其处理“缩放”消息
这种模块化设计已经允许定义不同类型的摄像机(比如固定摄像机没有<代码>可移动<代码>组件),将某些组件用于其他东西(另一种类型的实体可能使用“视图”),并且您还可以通过让不同的组件以不同的方式处理每条消息来获得灵活性
当然,可能需要一些优化技巧,特别是对于经常使用的消息。创建支持这种行为的组件怎么样?例如,InputComponent可以处理来自播放器的输入。然后,您的设计保持不变,播放器只是一个实体,允许从键盘输入,而不是从AI控制器输入。将相机和播放器制作成实体有什么好处?为什么它们不应该成为自己的东西,成为古怪的东西呢?我注意到,您描述的“玩家”实际上只是MVC的控制器端,不适用于其他玩家(如果存在)。我的主要观点是:不要创建一个创新的系统,只是为了让它成为一个球和链,阻止你在特殊情况下做正确的事情。@Mike:我希望我的实体系统是统一的。摄像机基本上只是一个有位置的实体,我发现这样做是合乎逻辑的,也是正确的。与播放器一样,没有更多,播放器具有物理实体的所有典型属性。难道你不能像其他独特功能一样为播放器和相机创建新的组件类型吗?@Jay:没有,但相机和播放器对我来说绝对是实体,它们是存在于世界空间中的物体。我认为将玩家(这是一个物理实体)的游戏内表现与玩家本身(世界的控制者)分开是一个好主意。同样地,你可以将相机作为实体(在世界上有一个位置)与相机的解释(渲染缩放等)分开。我不明白访客模式在这里有什么帮助。这是一种动态类型的调度机制。OP在问如何设计他的系统。我看不出它有什么关系,它简化了实体的专门化:例如,他可以只添加一个ZoomCameraComponent,而不涉及类层次结构。但我可能误解了这个问题。