基于组件的游戏引擎设计中的事件处理
我想这个问题或它的变体被广泛传播,所以如果我所说的是重复的,并且答案在其他地方,请通知我。
我一直在研究游戏引擎设计,并遇到了基于组件的实体模型。听起来很有希望,但我仍在研究它的实现。
我正在考虑一个系统,其中引擎由多个“子系统”组成,这些“子系统”管理某些方面,如渲染、声音、健康、人工智能等。每个子系统都有一个与之关联的组件类型,如健康的健康组件子系统。一个“实体”,例如 NPC、一扇门、某种视觉效果或玩家,只是由一个或多个组件组成,这些组件组合在一起赋予实体其功能。
我确定了信息传递的四个主要渠道:组件可以向其当前实体中的所有组件广播,组件可以向其子系统广播,子系统可以向其组件广播,子系统可以向其他子系统广播。
例如,如果用户想要移动他们的角色,他们会按一个键。该按键将由输入子系统接收,然后广播该事件并由播放器子系统接收。然后,玩家子系统将此事件发送到所有玩家组件(以及这些组件组成的实体),并且这些玩家组件将与其自己的实体的位置组件通信以继续前进并移动。
所有这些对于按键来说似乎有点啰嗦,我当然愿意对此架构进行改进。但无论如何,我的主要问题仍然存在。
至于事件本身,我考虑了事件在访问者模式中的行为。我想要的重要性是,如果一个事件遇到它不支持的组件(就像在移动事件中与 AI 或健康没有直接关系),它将忽略该组件。如果事件没有找到它要查找的组件,也没有关系。
访客模式几乎可以工作。然而,这需要我为每种类型的组件(即visitHealthComponent、visitPositionComponent等)提供虚拟函数,即使它与它们没有任何关系。我可以将这些函数留空(因此,如果它确实遇到了这些组件,它将被忽略),但每次添加组件时我都必须添加另一个函数。
我的希望是我能够添加一个组件而不必向其他地方添加东西,并且添加一个事件而不会弄乱其他东西。
所以,我的两个问题是:
- 我的设计在效率、灵活性等方面是否可以进行任何改进?
- 处理事件的最佳方式是什么?
I imagine this question or variations of it get passed around a lot, so if what I'm saying is a duplicate, and the answers lie elsewhere, please inform me.
I have been researching game engine designs and have come across the component-based entity model. It sounds promising, but I'm still working out its implementation.
I'm considering a system where the engine is arranged of several "subsystems," which manage some aspect, like rendering, sound, health, AI, etc. Each subsystem has a component type associated with it, like a health component for the health subsystem. An "entity," for example an NPC, a door, some visual effect, or the player, is simply composed of one or more components, that when together give the entity its functionality.
I identified four main channels of information passing: a component can broadcast to all components in its current entity, a component can broadcast to its subsystem, a subsystem can broadcast to its components, and a subsystem can broadcast to other subsystems.
For example, if the user wanted to move their characters, they would press a key. This key press would be picked up by input subsystem, which then broadcasts the event and would be picked up by the player subsystem. The player subsystem then sends this event to all player components (and thus the entities those components compose), and those player components would communicate to its own entity's position component to go ahead and move.
All of this for a key press seems a bit winded, and I am certainly open to improvements to this architecture. But anyway, my main question still follows.
As for the events themselves, I considered where an event behaves as in the visitor pattern. The importance of what I want is that if an event comes across a component it doesn't support (as in a move event has nothing directly to do with AI or health), it would ignore the component. If an event doesn't find the component it's going after, it doesn't matter.
The visitor pattern almost works. However, it would require that I have virtual functions for every type of component (i.e. visitHealthComponent, visitPositionComponent, etc.) even if it doesn't have anything to do with them. I could leave these functions empty (so if it did come across those components, it would be ignored), but I would have to add another function every time I add a component.
My hopes were that I would be able to add a component without necessarily adding stuff to other places, and add an event without messing with other stuff.
So, my two questions:
- Are there any improvements my design could allow, in terms of efficiency, flexibility, etc.?
- What would be the optimal way to handle events?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我一直在考虑在我自己的一个项目中使用实体系统,并且经历了类似的思考过程。我最初的想法是使用观察者模式来处理事件 - 我也最初考虑过某种访问者模式,但由于您提出的原因而决定反对它。
我的想法是,子系统将提供子系统特定的发布/订阅接口,因此子系统依赖性将以“半松散”耦合的方式解决。任何依赖于另一个子系统的事件的子系统都会知道该子系统的订阅者接口,因此可以有效地利用它。
不幸的是,这些订阅者如何获取他们的发布者的句柄在我看来仍然是一个问题。在这一点上,我赞成某种动态创建,其中每个子系统都被实例化,然后使用第二阶段来解决依赖关系并将所有子系统置于“就绪状态”。
不管怎样,我对你的成果以及你在项目中遇到的任何问题非常感兴趣:)
I have been thinking about using entity systems for one of my own projects and have gone through a similar thought process. My initial thought was to use an Observer pattern to deal with events - I too, originally considered some kind of visitor pattern, but decided against it for the very reasons you bring up.
My thoughts are that the subsystems will provide a subsystem specific publish/subscribe interface, and thus subsystem dependencies will be resolved in a "semi-loosely" coupled fashion. Any subsystem that depends on events from another subsystem will know of the subscriber interface to that subsystem and thus can effectively make use of it.
Unfortunately, how these subscribers get handles to their publishers is still somewhat of an issue in my mind. At this point, I am favoring some kind of dynamic creation where each subsystem is instantiated, and then a second phase is used to resolve the dependencies and put all the subsystems into a "ready state".
Anyway, I am very interested in what worked out for you and any problems you encountered on your project :)
使用事件总线,也称为事件聚合器。您想要的是一种不需要子系统之间耦合的事件机制,而事件总线就能做到这一点。
http://martinfowler.com/eaaDev/EventAggregator.html
http://stackoverflow.com/questions/2343980/event-aggregator-implementation-sample-best-practices
等
Use an event bus, aka event aggregator. What you want is an event mechanism that requires no coupling between subsystems, and an event bus will do just that.
http://martinfowler.com/eaaDev/EventAggregator.html
http://stackoverflow.com/questions/2343980/event-aggregator-implementation-sample-best-practices
etc
这里描述的这种架构 http://members.cox.net/jplummer/Writings/Thesis_with_Appendix.pdf
我在实际项目中实现这一点时至少遇到了三个问题:
我认为答案是具有抽象表示的分层架构......
this architecture described here http://members.cox.net/jplummer/Writings/Thesis_with_Appendix.pdf
There are at least three problems I encountered implementing this in a real project:
i think that answer is layered architectures with abstracted representation...
请原谅我糟糕的英语。
我正在编写一个基于实体组件系统的灵活且可扩展的 java 3d 游戏引擎。我已经完成了它的一些基本部分。
首先我想说一些关于ECS架构的事情,我不同意一个组件可以与同一实体中的其他组件进行通信。组件应该只存储数据,系统处理它们。
在事件处理部分,我认为基本的输入处理不应该包含在ECS中。相反,我有一个名为 Intent System 的系统,并有一个名为 Intent Component 的组件,其中包含许多意图。意图意味着实体想要对实体做某事。
意图系统处理所有的意图,当它处理一个意图时,它会将相应的信息广播到其他系统或向实体添加其他组件。
我还编写了一个名为 Intent Generator 的接口。在本地游戏中,您可以实现键盘输入或鼠标输入生成器,在多人游戏中,您可以实现网络意图生成器。在AI系统中,你还可以生成意图。
您可能认为意图系统在游戏中处理了太多的事情。但实际上,它共享了许多处理给其他系统,而且我还编写了一个脚本系统。对于特定的特殊实体,它有一个脚本组件来做特殊的事情。
最初当我开发一些东西时,我总是想做出一个伟大的架构,它包含了所有的东西。但对于游戏开发来说,有时效率很低。不同的游戏对象可能具有完全不同的功能。 ECS 作为面向数据的编程系统非常出色。但我们不能将所有内容都包含在一个完整的游戏中。
顺便说一句,我们基于ECS的游戏引擎将在不久的将来开源,届时您可以阅读。如果你对此感兴趣,我也邀请你加入我们。
Excuse my bad English.
I am writing a flexible and scalable java 3d Game Engine based on Entity-Component System. I have finished some basic parts of it.
First i want to say something about ECS architecture, I don't agree that a component can communicate with other components in a same entity. Components should only store data and systems process them.
In event handling part, I think the basic input handling should not be included in a ECS. Instead, I have a System called Intent System and have a Component called Intent Component which contains many intents. A intent means a entity wants to do something toward a entity.
the Intent System process all the intents, When it processes a intent, it broadcasts the corresponding information to other systems or add other components to the entity.
I also write a interface called Intent Generator. In local game, you can implement a Keyboard Input or Mouse Input Generator and in multiple-player game, you can implement network intent generator. In AI system, you can also generate intents.
You may think the Intent System processes too many things in the game. But in fact, it shares many processing to other systems And I also write a Script System. For specific special entity it has a script component doing special things.
Originally when I develop something, I always want to make a great architecture which includes every thing. But for game developing sometimes it is very inefficient. Different game object may have completely different functions. ECS is great as data-oriented programming system. but we can not include every thing in it for a complete game.
By the way, Our ECS-based game engine will be open source in near future, then you can read it. If u are interested in it, I also invite u to join us.