70
\$\begingroup\$

I am reading Game Coding Complete and the author recommends Event Driven communication among game objects and modules.

Basically, all living game actors should communicate with the key modules (Physics, AI, Game Logic, Game View, etc.) via an internal event messaging system. This means having to design an efficient event manager. A badly designed system eats CPU cycles, especially affecting mobile platforms.

Is this a proven and recommended approach? How should I decide whether to use it?

\$\endgroup\$
4
  • \$\begingroup\$ Hi James, thank you for your answer. I like it, although the book describes Event Driven communication as really complex system seemingly consuming significantly a lot of CPU resources. \$\endgroup\$ Jan 25, 2011 at 19:59
  • \$\begingroup\$ Put it into an answer and added in a link to high level overview of an event messaging system I gave as an answer over on stack overflow. Enjoy! Just remember that what some people consider complex doesn't have to be :) \$\endgroup\$
    – James
    Jan 25, 2011 at 20:46
  • 1
    \$\begingroup\$ You can check this answer as well done using c++11: stackoverflow.com/a/22703242/2929762 \$\endgroup\$ Mar 28, 2014 at 2:49
  • \$\begingroup\$ libuv has recently emerged as a successful events library. (It's in C. Node.js is its most famous use-case.) \$\endgroup\$
    – Anko
    Mar 28, 2014 at 10:55

8 Answers 8

50
\$\begingroup\$

This is an expansion of my comment to a full answer, as suggested.

Yes, plain and simple. Communication needs to happen and while there are situations where 'Are we there yet?'-type polling is required, having things check to see if they should be doing something else generally wastes time. You could instead have them react to things they are told to do. Plus, a well defined communication pathway between objects/systems/modules boosts parallel setups significantly.

I've given a high-level overview of an event messaging system over on Stack Overflow. I have used it from school into professional gaming titles and now non-gaming products, adapted to the use case every time of course.

EDIT: To address a comment question on how do you know which objects should get the message: The objects themselves should Request to be notified about events. Your EventMessagingSystem (EMS) will need a Register(int iEventId, IEventMessagingSystem * pOjbect, (EMSCallback)fpMethodToUseForACallback) as well as a matching Unregister (making a unique entry for an iEventId out of the object pointer and callback). This way, when an object wants to know about a message it can Register() with the system. When it no longer needs to know about the events, it can Unregister(). Clearly, you'd want a pool of these callback registration objects and an effective way to add/remove them from lists. (I've usually used self ordering arrays; a fancy way of saying they track their own allocations between a pool stack of unused objects and arrays that shift their sizes in place when needed).

EDIT: For a completely working game with an update loop and an event messaging system, you might want to check out an old school project of mine. The Stack Overflow post linked above also refers to it.

\$\endgroup\$
10
  • \$\begingroup\$ Hello James, as I am thinking about internal event messaging system more, I think it does not need to add more cost to the engine. For example, if there are 50 objects on the screen, but only 5 of them are supposed to change their behavior; under traditional system, all the 50 obejcts would need to check for all their possible actions, to see if they should do something. However, with the usage of event messaging, only 5 messages will be sent to those 5 obejects with specific change of action. That looks like a time saving approach. \$\endgroup\$ Jan 25, 2011 at 20:55
  • 1
    \$\begingroup\$ The way the system linked to in my above answer works is that objects only register to hear about the messages they want.. We would use this to our advantage in video games where there may be 100-200 objects in a level, but you only 'activate' the ones the player can directly interact with, keeping the number of things listening down to about 10 or so. All in all this type of system should be 'smarter' than an 'are we there yet?' polling system, and should reduce the overhead of an engine, atleast as far as communication is concerned. \$\endgroup\$
    – James
    Jan 25, 2011 at 21:12
  • 1
    \$\begingroup\$ There is one thing related to event driven system that confuses me: Under traditional system where every object has predefined set of methods (OnUpdate(), OnMove(), OnAI(), OnCollisionCheck()...) regularly called, every object is resposnsible for checking and managing its state. Under event driven system, there must be some master system chcecking condition of every object, and then sending messages to those where some event was detected. To me, this standardizes the possible object states, and limits the freedom to create unique object behavior. Is that true? \$\endgroup\$ Jan 25, 2011 at 21:24
  • 1
    \$\begingroup\$ The Observer pattern is the typical alternative to polling. en.wikipedia.org/wiki/Observer_pattern \$\endgroup\$
    – Ricket
    Jan 25, 2011 at 21:28
  • 1
    \$\begingroup\$ @hamlin11 Glad this information is still helping people :) In regards to the registration, if this happens quite a bit, remember you will want to optimize it for speed, have a pool of the registration objects to draw from, etc. \$\endgroup\$
    – James
    Apr 4, 2011 at 15:48
23
\$\begingroup\$

My opinion is that you should just start making your game and implement what you're comfortable with. As you do that you'll find yourself using MVC some places, but not others; events some places, but not others; components some places, but inheritance others; clean design some places, and crufty design others.

And that's OK, because when you're done you'll actually have a game, and a game is way cooler than a message-passing system.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Hi Joe, thanks for your answer, I like it. You believe, that there is no need to push any aproach artifically. I should design applications as I think would work, and if something does not work later, I will simply redo it. \$\endgroup\$ Jan 25, 2011 at 19:53
  • \$\begingroup\$ This is why the system exists. Many people have done just what you've said, witnessed the nightmare, and said there has to be a better way. You can either repeat thier mistakes or learn from them and maybe advance it more. \$\endgroup\$
    – user441521
    Jul 20, 2017 at 19:51
19
\$\begingroup\$

Messages generally work well when:

  1. The thing sending the message doesn't care if it gets received.
  2. The sender does not need to get an immediate response back from the receiver.
  3. There may be multiple receivers listening to a single sender.
  4. Messages will be sent infrequently or unpredictably. (In other words, if every object needs to get an "update" message every single frame, messages aren't really buying you much.)

The more your needs match that list, the better of a fit messages will be. At a very general level, they're pretty good. They do a good job of not wasting CPU cycles just to do nothing unlike polling or other more global solutions. They are fantastic at decoupling parts of a codebase, which is always helpful.

\$\endgroup\$
18
\$\begingroup\$

A better question is, what alternatives are there? In such a complex system with properly divided modules for physics, AI, etc., how else can you orchestrate these systems?

Message passing does seem to be the "best" solution to this problem. I can't think of alternatives right now. But there are plenty of examples of message passing in practice. In fact, operating systems use message passing for several of their functions. From Wikipedia:

Messages are also commonly used in the same sense as a means of interprocess communication; the other common technique being streams or pipes, in which data are sent as a sequence of elementary data items instead (the higher-level version of a virtual circuit).

(Interprocess communication is the communication between processes (i.e. running instances of programs) within the operating system environment)

So if it's good enough for an operating system, it's probably good enough for a game, right? There are other benefits as well, but I'll let the Wikipedia article on message passing do the explaining.

I also asked a question on Stack Overflow, "Data structures for message passing within a program?", which you might want to read over.

\$\endgroup\$
5
  • \$\begingroup\$ Hi Ricket, thanks for your answer. You asked what other ways could be used to let the game objects communicate each other. What comes to my mind is direct methods calls. It is corect, that it does not give you so much flexibility, but on the other hand, it avoids event message generation, passing, reading, etc.. We still talk about mobile platforms, not about high-end games. Operating system havily uses internal messaging system. However, it is not designed to run in real-time, where even small delays cause disruptions. \$\endgroup\$ Jan 25, 2011 at 19:29
  • \$\begingroup\$ Let me keep this question open for a while. I would like to gather more opinions, before closing it. \$\endgroup\$ Jan 25, 2011 at 19:30
  • 1
    \$\begingroup\$ Direct method calls generally result in coupling of the classes who call each other. This isn't good for a system separated into components which are supposed to be interchangeable. There are some patterns which can facilitate direct method calls with less cohesion (e.g. the "controller" part of MVC basically serves this purpose for facilitating view's queries of the model, unless you couple them) but in general, message passing is the only way for a system to have zero coupling between subsystems (or at least the only way I know of). \$\endgroup\$
    – Ricket
    Jan 25, 2011 at 21:28
  • \$\begingroup\$ Ah, so now we started discussing patterns. I have heard a bit about this programming approach. Now, I start understanding what patterns are. It is completely different look at the application design. You masivelly control objects, while using the same code to check every object. After checking the object you set its attributes accordingly. \$\endgroup\$ Jan 25, 2011 at 21:41
  • 1
    \$\begingroup\$ The "Data Structures..." question has an AMAZING answer. I'd say, your selected answer and the accompanying Nebula3 article are the best description of game engine architecture of their size I've ever seen. \$\endgroup\$
    – deft_code
    Jan 26, 2011 at 15:58
7
\$\begingroup\$

Great answers so far from James and Ricket, I only answer to add a note of caution. Message passing / event driven communication is certainly an important tool in the developer's arsenal, but it can easily be overused. When you have a hammer, everything looks like a nail, and so on.

You absolutely, 100%, should be thinking about the flow of data around your title, and be fully aware of how information is passing from one subsystem to another. In some cases message passing is clearly best; in others, it may be more appropriate for one subsystem to operate over a list of shared objects, allowing other subsystems to also operate on the same shared list; and many more methods besides.

At all times you should be aware of which subsystems need access to which data, and when they need to access it. This affects your ability to parallelise and optimise, as well as helping you avoid the more insidious problems when different parts of your engine become too closely entwined. You need to be thinking about minimising unnecessary copying around of data, and how your data layout affects your cache usage. All of which will guide you to the best solution in each case.

That being said, pretty much every game I've ever worked on has had a solid asynchronous message passing / event notification system. It allows you to write succinct, efficient maintainable code, even in the face of complex and quickly changing design needs.

\$\endgroup\$
1
  • \$\begingroup\$ +1 for good additional info. Hi, MrCranky, Thanks. According to what you say, it sould be well worth of considering Event Messaging system even for mobile games. However, planning should not be overlooked, and it should be very well considered where the messaging system will be used. \$\endgroup\$ Feb 12, 2011 at 2:21
5
\$\begingroup\$

Yes. It is a very efficient way for game systems to communicate with each other. Events help you decouple many systems and make it possible to even compile things separately without knowing of each others' existence. This means your classes can be more easily prototyped and the compilation times are faster. More importantly, you end up with a flat code design instead of a dependency mess.

Another big benefit of events is that they are easily streamed over a network or other text channel. You can record them for later playback. The possibilities are endless.

Another benefit: You can have several subsystems listening for the same event. For example, all your remote views (players) can automatically subscribe to the entity creation event and spawn entities on each client with little work on your part. Imagine how much more work it would be if you did not use events: you would have to place Update() calls somewhere or maybe call view->CreateEntity from the Game logic (where knowledge about the view and what information it requires doesn't belong). It's hard to solve that problem without events.

With events you get an elegant and decoupled solution that supports infinite number of objects of unlimited kinds that can all simply subscribe to events and do their thing when something happens in your game. That's why events are great.

More details and an implementation here.

\$\endgroup\$
3
  • \$\begingroup\$ Great points, though one-sided. I'm always suspicious of generality: Are there anti-use-cases for events? \$\endgroup\$
    – Anko
    Mar 28, 2014 at 10:34
  • 1
    \$\begingroup\$ Anti-use points: when you absolutely must have direct response. When whatever you want to do upon some event is always executed directly and in the same thread. When there is absolutely no outside delay that may delay the calls completion. When you have only linear dependencies. When you rarely do multiple things simultaneously. If you look at node.js, all io calls are event based. Node.js is one place where events have been implemented 100% correctly. \$\endgroup\$ Mar 29, 2014 at 17:00
  • \$\begingroup\$ The event system doesn't need to be async. You can use coroutines to simulate async, while getting sync when you need it. \$\endgroup\$
    – user441521
    Jul 20, 2017 at 19:59
4
\$\begingroup\$

Well, I know that this post is quite old , but I could not resist.

I recently built a game engine. It uses 3d party libraries to rendering and physics, but I wrote the core part, that defines and processes the entities and game logic.

The engine surely follows a traditional approach. There is a main update loop that calls update function for all entities. Collisions are directly reported by callback on the entities. Communications between entities are made using smart pointers exchanged between entities.

There is a primitive message system, That processes only a small group of entity to engine messages. Those messages are preferable to be processed at the end of a game interaction ( example is a entity creation or destruction ) because they can mess with the update list. So , at the end of each game loop, a small list of messages are consumed.

Despite the primitive message system , I would say that the system is largely "update loop based".

Well. After using this system, I think that it is very simple, fast and well organized. The game logic is visible and self contained inside entities, not dynamic like a message quewe. I really would not to make it event driven because in my opinion event systems introduce unnecessary complexity to the game logic , and make the game code very difficult to understand and debug.

But, I also think that a pure "update loop based" system like mine have some problems too.

For example, In some moments, one entity may be at a " do nothing state " , may be waiting the player approaching or something else. In most of those cases , the entity burns processor time for nothing and its is better to turn the entity off, and turn it on when a certain event happens.

So, in my next game engine , I am going to adopt a different approach. Entities will register themselves for engine operations, like update, drawing, collision detection and so one. Each of these events will have separated lists of entity interfaces for the actual entities.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You'll find that entities become monster code bases that become hard to manage with any sort of complexity in the game. You'll end up coupling them together and it'll suck to add or change features. By breaking your features into small components it'll be easier to maintain and add features. Then the question becomes how do these components communicate? The answer is events from one component raising functions of another while passing primitive data along in the arguments. \$\endgroup\$
    – user441521
    Jul 20, 2017 at 19:55
2
\$\begingroup\$

From what I have seen, it doesn't seem to be very common to have an engine completely based on messaging. Of course, there are subsystems which lend themselves very well to such a messaging system, like networking, GUI, and possibly others. In general though, there are a few problems I can think of:

  • Game engines deal with large amounts of data.
  • Games have to be fast (20-30 FPS should be the minimum).
  • Often it is necessary to know if something has been done or when it will be done.

With the common game developer approach of "it has to be efficient as possible" such messaging system are thus not that common.

However, I agree that you should just go ahead and try it. There certainly are lots advantages with such a system and computing power is cheaply available today.

\$\endgroup\$
2
  • \$\begingroup\$ I don't know if I agree with this. The alternative is polling which is wasteful. Responding to events only is the most efficient. Yes, there will still be some polling that will happen and raise events but there are a good number of things that are event oriented as well. \$\endgroup\$
    – user441521
    Jul 21, 2017 at 11:49
  • 1
    \$\begingroup\$ I don't agree with this either. The amount of data game engines deal with is largely irrelevant, as event messaging is designed for subsystem-subsystem communication. Game objects should not communicate with other game objects directly (though custom event handlers in objects could be an exception). Due to this relatively small number of subsystems, and their areas of "interest", the performance cost of a well designed messaging backbone, in a multi-threaded engine is negligible. \$\endgroup\$
    – Ian Young
    Aug 17, 2018 at 10:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .