基于组件的游戏引擎设计中的事件处理

时间:2010-09-14 03:17:59

标签: oop components game-engine visitor

我想这个问题或其中的变化会被传递很多,所以如果我说的是重复的,答案在别处,请通知我。

我一直在研究游戏引擎设计,并且遇到了基于组件的实体模型。这听起来很有希望,但我仍在努力实施它。

我正在考虑一个系统,其中引擎安排了几个“子系统”,它管理一些方面,如渲染,声音,健康,AI等。每个子系统都有一个与之关联的组件类型,如健康组件对于健康子系统。 “实体”,例如NPC,门,某些视觉效果或播放器,仅由一个或多个组件组成,这些组件在一起为实体提供其功能。

我确定了四个主要的信息传递渠道:一个组件可以广播到其当前实体中的所有组件,一个组件可以广播到其子系统,一个子系统可以广播到其组件,一个子系统可以广播到其他子系统。 / p>

例如,如果用户想要移动他们的角色,他们会按一个键。此按键将由输入子系统拾取,然后输入子系统广播该事件并由播放器子系统拾取。然后,播放器子系统将此事件发送给所有播放器组件(以及这些组件组成的实体),并且这些播放器组件将与其自己的实体的位置组件进行通信以继续前进并移动。

所有这一切对于一个关键的新闻似乎有点啰嗦,我当然愿意改进这种架构。但无论如何,我的主要问题仍然存在。

至于事件本身,我考虑了事件在访客模式中的行为。我想要的重要性是,如果一个事件遇到它不支持的组件(因为在移动事件中没有与AI或健康直接相关),它将忽略该组件。如果一个事件没有找到它正在追踪的组件,那就无所谓了。

访客模式几乎可行。但是,它需要我为每种类型的组件(即visitHealthComponent,visitPositionComponent等)提供虚函数,即使它与它们没有任何关系。我可以把这些函数留空(所以如果碰到那些组件,就会被忽略),但每次添加组件时我都要添加另一个函数。

我希望我能够添加一个组件,而不必将东西添加到其他地方,并添加一个事件而不会弄乱其他东西。

所以,我的两个问题:

  1. 在效率,灵活性等方面,我的设计是否有任何改进?
  2. 处理事件的最佳方式是什么?

4 个答案:

答案 0 :(得分:1)

我一直在考虑将实体系统用于我自己的一个项目,并且经历了类似的思考过程。我最初的想法是使用观察者模式来处理事件 - 我也是最初被认为是某种访问者模式,但是由于你提出的原因而决定反对它。

我的想法是子系统将提供子系统特定的发布/订阅接口,因此子系统依赖性将以“半松散”耦合的方式解决。依赖于来自另一个子系统的事件的任何子系统都将知道该子系统的用户接口,因此可以有效地利用它。

不幸的是,这些订阅者如何获得发布商的处理权仍然是我的一个问题。在这一点上,我赞成某种动态创建,其中每个子系统都被实例化,然后第二阶段用于解析依赖关系并将所有子系统置于“就绪状态”。

无论如何,我对你的成功以及你在项目中遇到的任何问题非常感兴趣:)

答案 1 :(得分:1)

使用事件总线,即事件聚合器。你想要的是一个事件机制,它不需要子系统之间的耦合,事件总线也可以做到这一点。

http://martinfowler.com/eaaDev/EventAggregator.html http://stackoverflow.com/questions/2343980/event-aggregator-implementation-sample-best-practices

答案 2 :(得分:1)

此处描述的此架构http://members.cox.net/jplummer/Writings/Thesis_with_Appendix.pdf 在实际项目中我遇到至少三个问题:

  1. 当事情发生时,系统不会得到通知 - 唯一的方法是询问它 - 玩家已经死了?墙不可见?等等 - 为了避免这种情况,您可以使用简单的MVC而不是观察者模式。
  2. 如果你的对象是一个复合(即由对象组成)怎么办?系统将遍历所有层次结构并询问组件状态。
  3. 主要的缺点是这种架构混合在一起 - 例如为什么玩家需要知道你按下了钥匙?
  4. 我认为答案是具有抽象表示的分层架构......

答案 3 :(得分:1)

请原谅我糟糕的英语。

我正在编写一个基于实体组件系统的灵活且可扩展的java 3d游戏引擎。我已经完成了它的一些基本部分。

首先,我想谈谈ECS架构,我不同意组件可以与同一实体中的其他组件进行通信。组件应该只存储数据和系统处理它们。

在事件处理部分,我认为基本输入处理不应包含在ECS中。相反,我有一个名为Intent System的系统,并且有一个名为Intent Component的Component,它包含许多意图。意图意味着实体想要对实体做某事。 Intent System处理所有意图,当它处理一个意图时,它会将相应的信息广播到其他系统或将其他组件添加到实体。

我还编写了一个名为Intent Generator的接口。在本地游戏中,您可以实现键盘输入或鼠标输入生成器,在多玩家游戏中,您可以实现网络意图生成器。在AI系统中,您还可以生成意图。

您可能认为Intent System在游戏中处理了太多事情。但实际上,它与其他系统共享许多处理。我还编写了一个脚本系统。对于特定的特殊实体,它有一个脚本组件做特殊事情。

最初,当我开发某些东西时,我总是想要制作一个包含所有东西的伟大建筑。但对于游戏开发有时效率非常低。不同的游戏对象可能具有完全不同的功能ECS非常适合作为面向数据的编程系统。但是我们不能在其中包含完整游戏的所有内容。

顺便说一下,我们基于ECS的游戏引擎将在不久的将来开源,然后你就可以阅读了。如果您对此感兴趣,我也邀请您加入我们。