10

我想这个问题或它的变体得到了很多传播,所以如果我说的是重复的,而答案在别处,请通知我。

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

我正在考虑一个系统,其中引擎由几个“子系统”组成,这些“子系统”管理某些方面,如渲染、声音、健康、人工智能等。每个子系统都有一个与之关联的组件类型,比如健康的健康组件子系统。一个“实体”,例如一个 NPC、一扇门、一些视觉效果或玩家,简单地由一个或多个组件组成,当它们一起赋予实体其功能时。

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

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

按键操作的所有这些似乎有点啰嗦,我当然愿意改进这个架构。但无论如何,我的主要问题仍然存在。

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

访问者模式几乎可以工作。但是,它要求我对每种类型的组件(即 visitHealthComponent、visitPositionComponent 等)都有虚函数,即使它与它们没有任何关系。我可以将这些函数留空(因此,如果确实遇到了这些组件,它将被忽略),但是每次添加组件时我都必须添加另一个函数。

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

所以,我的两个问题:

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

4 回答 4

1

使用事件总线,也就是事件聚合器。您想要的是一种不需要子系统之间耦合的事件机制,而事件总线将做到这一点。

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

ETC

于 2010-12-21T09:39:07.227 回答
1

原谅我的英语不好。

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

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

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

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

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

最初,当我开发一些东西时,我总是想制作一个包含所有东西的伟大架构。但是对于游戏开发来说,有时效率非常低。不同的游戏对象可能具有完全不同的功能。ECS 作为面向数据的编程系统非常棒。但我们不能将所有东西都包含在一个完整的游戏中。

顺便提一下,我们基于ECS的游戏引擎近期会开源,大家可以阅读一下。如果你对此感兴趣,我也邀请你加入我们。

于 2014-05-13T02:00:45.510 回答
1

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

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

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

无论如何,我对为您解决的问题以及您在项目中遇到的任何问题非常感兴趣 :)

于 2010-10-28T22:25:40.677 回答
1

这里描述的这个架构http://members.cox.net/jplummer/Writings/Thesis_with_Appendix.pdf 在一个真实的项目中我遇到了至少三个问题:

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

我认为答案是具有抽象表示的分层架构......

于 2011-05-21T17:54:35.630 回答