我想这个问题或它的变体得到了很多传播,所以如果我说的是重复的,而答案在别处,请通知我。
我一直在研究游戏引擎设计,并遇到过基于组件的实体模型。这听起来很有希望,但我仍在研究它的实现。
我正在考虑一个系统,其中引擎由几个“子系统”组成,这些“子系统”管理某些方面,如渲染、声音、健康、人工智能等。每个子系统都有一个与之关联的组件类型,比如健康的健康组件子系统。一个“实体”,例如一个 NPC、一扇门、一些视觉效果或玩家,简单地由一个或多个组件组成,当它们一起赋予实体其功能时。
我确定了四个主要的信息传递 channel :一个组件可以广播到其当前实体中的所有组件,一个组件可以广播到它的子系统,一个子系统可以广播到它的组件,一个子系统可以广播到其他子系统。
例如,如果用户想要移动他们的角色,他们会按下一个键。这个按键将被输入子系统拾取,然后广播事件并被播放器子系统拾取。播放器子系统然后将此事件发送到所有播放器组件(以及这些组件组成的实体),并且这些播放器组件将与其自身实体的位置组件通信以继续移动。
按键操作的所有这些似乎有点啰嗦,我当然愿意改进这个架构。但无论如何,我的主要问题仍然存在。
至于事件本身,我考虑了事件在访问者模式中的行为。我想要的重要性在于,如果事件遇到它不支持的组件(因为在移动事件中与 AI 或健康没有直接关系),它将忽略该组件。如果一个事件没有找到它所追求的组件,那也没关系。
访问者模式几乎可以工作。但是,它要求我对每种类型的组件(即 visitHealthComponent、visitPositionComponent 等)都有虚函数,即使它与它们没有任何关系。我可以将这些函数留空(因此,如果确实遇到了这些组件,它将被忽略),但是每次添加组件时我都必须添加另一个函数。
我的希望是我能够添加一个组件而不必在其他地方添加东西,并且添加一个事件而不会弄乱其他东西。
所以,我的两个问题:
最佳答案
我一直在考虑将实体系统用于我自己的一个项目,并且经历了类似的思考过程。我最初的想法是使用观察者模式来处理事件——我也是,最初考虑过某种访问者模式,但出于你提出的原因决定反对它。
我的想法是子系统将提供子系统特定的发布/订阅接口(interface),因此子系统依赖关系将以“半松散”耦合的方式解决。任何依赖于来自另一个子系统的事件的子系统都将知道该子系统的订阅者接口(interface),因此可以有效地利用它。
不幸的是,这些订阅者如何处理他们的发布者在我看来仍然是一个问题。在这一点上,我倾向于某种动态创建,其中每个子系统都被实例化,然后使用第二阶段来解决依赖关系并将所有子系统置于“就绪状态”。
无论如何,我对为您解决的问题以及您在项目中遇到的任何问题非常感兴趣 :)
关于oop - 基于组件的游戏引擎设计中的事件处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3705884/