Component based architecture and messaging

Started by
18 comments, last by Reitano 10 years, 7 months ago

Hello,

I have a component based architecture with subsystems, which hold the component data and implement the game logic. Now a great problem is, how to implement a messaging system.

I have a message dispatcher system, with template where every message type registers it's own eventhandler. On Dispatch every function in the list will be called. I don't like this, because it's hard to delete one listener and I don't get how a message queue could be implemented.

So I think of a design like that every subsystem has it's own queue and a high level system (e.g. world manager, ...) write to this queue if anything needs to be updated. One problem is, I think, that every high level system needs to know about the low level systems.

Is this a good approach? How do you think about coupling/decoupling, because coupling would be the case in my idea.

Dominik

Advertisement
Most people will tend towards decoupling out of efficiency, being easier to change components. Coupling can work, and can (I stress 'can') be faster to implement as well as be faster overall, however your system will be less robust and will be far more fragile.

Your second idea does not require 'coupling' as I would understand it. Have you looked at Service Oriented Architectures? I think it would fit well and is a decoupled system.

Don't over-engineer something which can be easily modeled in a simplistic fashion and changed later if the need arises.

The premise behind a component based architecture isn't to abolish coupling completely, but to hide that coupling effectively so that designers can easily combine a set of features exposed through an API to create unique and creative game objects with ease. So what becomes important to us developers is how and where we implement the coupling.

The simplest of approaches would be to leverage the observer pattern; allowing systems to register as a listener to other systems. Depending on your approach, this may lead to the massive switch statement event handler or too an excessive multiple inheritance problem. I'd argue if you end up with either, chances are the system is likely doing too much and might suffice for being split into smaller chunks of behavior.

Another approach would be to have a system expose a set of event objects that another system could subscribe/unsubscribe as needed. These event objects are analogous to signal/slots which can be found in boost and several other libraries. The benefit is that using signal/slots, the connection between the subscriber and publisher can be cleaned up when either go out of scope. Function callbacks are wonderful constructs, but do be weary of their side affects, particularly on your cache if over used inside your main game loop.

One last approach would involve reversing the flow of data. In the above two scenarios, you're pushing data from a higher level system to the lower systems, but sometimes it can be far more efficient and flexible to poll for information depending on circumstances.

In this case, you have an event buffer that holds events your game loop has fired in the current frame sorted by time. When a system processes it's update tick, it checks whether any events of interest exist in the event buffer and processes them. This would allow you to skip events if multiple ones exist and it would also allow events to be popped from the event buffer and replaced with modified versions that perhaps are of interest to a system that fires later in the update cycle too (e.g. system that modifies damage event based on armor, shields, absorbs, etc.). In this case, you can easily store the events placed in the buffer for later playback if that was something of interest.

I think, one great possibility is to go the third way, because every system can take the event that it can consume, but how can I implement this, without one big switch in every system. I think this is a very bad solution. Should I static_cast the event parameter?

In my event system (unbufferd) I have function calls, so it's easy to have the right parameter. But a solution with a big switch and a static_cast is simply ugly I think.

I think you have this event queue in the game loop class?

I have thought about a basic architecture, what I need in my game. I want a car to go to different points controlled by AI.

So I think I have following low level systems: Render system, Physic system (optional), Position system, AI system, Waypoint system.

High level system would be exactly one Entity sytem, which has references to all the low level systems, because it needs to know everything from above.

Is this correct? Is a component system structured this way?

There are numerous ways to structure your events and they don't necessarily have to be classes. Remember, one could easily just treat the event queue as a raw buffer of data and with some bookkeeping constructs, one could easily iterate the events perhaps by id within the raw buffer. Events after all are just data, right? :)

The important thing to realize with a callback mechanism is that when you execute the callback immediately when the event happens, you often trash your instruction and data caches and this is particularly bad in games. For example event A fires callback A. While processing callback A, a condition is met that must fire event B that in turn fires callback B. Inside callback B, a condition is met that must fire another event. You can quickly see how your instruction/data caches can get trashed.

Just make sure that if you move forward with such an event system that it offers both asynchronous and synchronous invocations of your callbacks. In the case of asynchronous, you queue up the events and a dispatch call at some future point issues all the callbacks in a loop where synchronous would fire the callback for a specific event at the time you emit the event.

You can place this queue where-ever is applicable for your code base. In my engine, I have a framework class which exposes a number of core engine components through the framework interface since the framework interface is generally injected into all classes during initialization or construction.

I think, one great possibility is to go the third way, because every system can take the event that it can consume, but how can I implement this, without one big switch in every system. I think this is a very bad solution. Should I static_cast the event parameter?

In my event system (unbufferd) I have function calls, so it's easy to have the right parameter. But a solution with a big switch and a static_cast is simply ugly I think.

I think you have this event queue in the game loop class?

I have thought about a basic architecture, what I need in my game. I want a car to go to different points controlled by AI.

So I think I have following low level systems: Render system, Physic system (optional), Position system, AI system, Waypoint system.

High level system would be exactly one Entity sytem, which has references to all the low level systems, because it needs to know everything from above.

Is this correct? Is a component system structured this way?

I'd say a bit of this is a matter of taste.

There is no right or wrong answer on how to design a component system because while games are starting to shift and ship with some component system like concepts, it's still something that depending on the development team and architect who is at the helm of the design process; it all varies and sometimes significantly.

I generally prefer the idea that the entity framework is a core component to the engine. The entity framework exposes an entity manager along with a component system interface. The developers create derived classes of the component system interface for whatever logic they want to implement for the designers. These component systems are then registered with the entity manager at start-up, allowing the entity manager to build a repository of meta data about the available components, properties associated with the components (useful for editors), etc.

The beauty is that with the entity manager having all this metadata at it's finger tips, the engine simply exposes the entity manager to the remainder of the application. Internally, the entity manager can delegate creation and destruction of components to the appropriate component systems without the developer having to find the right system and call it directly. Our component system interface is also designed so that the component system can interact with our core engine framework and submit jobs to the task manager, register themselves as callback listeners to various systems, etc.

I have thought about a basic architecture, what I need in my game. I want a car to go to different points controlled by AI.

So I think I have following low level systems: Render system, Physic system (optional), Position system, AI system, Waypoint system.

High level system would be exactly one Entity sytem, which has references to all the low level systems, because it needs to know everything from above.

Is this correct? Is a component system structured this way?

I'd say a bit of this is a matter of taste.

There is no right or wrong answer on how to design a component system because while games are starting to shift and ship with some component system like concepts, it's still something that depending on the development team and architect who is at the helm of the design process; it all varies and sometimes significantly.

I generally prefer the idea that the entity framework is a core component to the engine. The entity framework exposes an entity manager along with a component system interface. The developers create derived classes of the component system interface for whatever logic they want to implement for the designers. These component systems are then registered with the entity manager at start-up, allowing the entity manager to build a repository of meta data about the available components, properties associated with the components (useful for editors), etc.

The beauty is that with the entity manager having all this metadata at it's finger tips, the engine simply exposes the entity manager to the remainder of the application. Internally, the entity manager can delegate creation and destruction of components to the appropriate component systems without the developer having to find the right system and call it directly. Our component system interface is also designed so that the component system can interact with our core engine framework and submit jobs to the task manager, register themselves as callback listeners to various systems, etc.

I like your architecture and edited my architecture diagram to this:

http://i40.tinypic.com/2wggbuu.png

So I think, it's very similar to your description.

I like your architecture and edited my architecture diagram to this:

http://i40.tinypic.com/2wggbuu.png

So I think, it's very similar to your description.

The only thing I'd caution you and possibly others about from your diagram is what you call Render System. I often consider the rendering system the renderer, the system that interacts with OpenGL or DirectX. The rendering system is typically something exposed by the engine itself much in the same light Physics, Input, Platform I/O, Networking, and Audio are exposed.

Then you create specialized component subsystems you register with the entity framework that handle specialized behaviors. This way you can have many component subsystems that perhaps handle specific rendering features, allowing each of those component subsystems to interact with the engine's rendering system.

I have edited the diagram, now I have a render manager, and a render system component. It's better I think, what I don't know is, if the waypoint system should be a system or manager. It' has notihing to do with the entity itself... Hmm....

http://i39.tinypic.com/oqg4sy.png

This topic is closed to new replies.

Advertisement