11
\$\begingroup\$

I'm creating a component-based game object system. Some tips:

  1. GameObject is simply a list of Components.
  2. There are GameSubsystems. For example, rendering, physics etc. Each GameSubsystem contains pointers to some of Components. GameSubsystem is a very powerful and flexible abstraction: it represents any slice (or aspect) of the game world.

There is a need in a mechanism of registering Components in GameSubsystems (when GameObject is created and composed). There are 4 approaches:


  • 1: Chain of responsibility pattern. Every Component is offered to every GameSubsystem. GameSubsystem makes a decision which Components to register (and how to organize them). For example, GameSubsystemRender can register Renderable Components.

pro. Components know nothing about how they are used. Low coupling. A. We can add new GameSubsystem. For example, let's add GameSubsystemTitles that registers all ComponentTitle and guarantees that every title is unique and provides interface to quering objects by title. Of course, ComponentTitle should not be rewrited or inherited in this case. B. We can reorganize existing GameSubsystems. For example, GameSubsystemAudio, GameSubsystemRender, GameSubsystemParticleEmmiter can be merged into GameSubsystemSpatial (to place all audio, emmiter, render Components in the same hierarchy and use parent-relative transforms).

con. Every-to-every check. Very innefficient.

con. Subsystems know about Components.


  • 2: Each Subsystem searches for Components of specific types.

pro. Better performance than in Approach 1.

con. Subsystems still know about Components.


  • 3: Component registers itself in GameSubsystem(s). We know at compile-time that there is a GameSubsystemRenderer, so let's ComponentImageRender will call something like GameSubsystemRenderer::register(ComponentRenderBase*).

pro. Performance. No unnecessary checks as in Approach 1.

con. Components are badly coupled with GameSubsystems.


  • 4: Mediator pattern. GameState (that contains GameSubsystems) can implement registerComponent(Component*).

pro. Components and GameSubystems know nothing about each other.

con. In C++ it would look like ugly and slow typeid-switch.


Questions: Which approach is better and mostly used in component-based design? What Practice says? Any suggestions about implementation of Approach 4?

Thank you.

\$\endgroup\$
4
  • \$\begingroup\$ I smell over-engineering. Components register themselves with GameObject. If GameSubsystem is what I think it is, then it's just a list of components that can be added to a GameObject at once. How you describe it sounds like there is some kind of "magic" how GameObjects and Components get together (they search for each other? Why?). I also get the feeling that you're trying to use components for basically everything in your engine, which I would also reconsider. For what it's worth I would only consider options 3 or 4. \$\endgroup\$
    – CodeSmile
    Commented Oct 17, 2010 at 18:30
  • \$\begingroup\$ @GamingHorror, Registering Components in GameObjects is out of scope of my question. Read articles about component-based approach or ask you own question on this site if you are interested in it. What you think about GameSubsystem is totally wrong. \$\endgroup\$
    – topright
    Commented Oct 17, 2010 at 20:18
  • \$\begingroup\$ I'm biased towards developing components for game logic, not engine components, and your description seemed to point in that direction. I understand component systems very well, I'm thinking I was thrown off course because I'm not familiar with the terminology you used, specifically GameSubsystem. From what I read, it sounded like you were trying to build everything (eg the whole engine) just from components. \$\endgroup\$
    – CodeSmile
    Commented Oct 19, 2010 at 0:25
  • \$\begingroup\$ Yes, "Component-based game objects" and "Component-oriented programming" are different terms, it can be confusing. Don't be biased, better be "bilased": scottbilas.com/files/2002/gdc_san_jose/game_objects_slides.ppt \$\endgroup\$
    – topright
    Commented Oct 19, 2010 at 1:34

1 Answer 1

3
\$\begingroup\$

Door number 3... Component registers itself in GameSubsystem(s)

The component is in place to keep the coupling abstracted from the GameObject itself. Somehow, somewhere something does in fact need to interact with the subsystems and this is the component and its purpose.

The coupling isn't actually a bad thing in this case.

The performance is essentially required in this case if you expect to have any complexity in your system, you just can't afford the search style approaches of the other options.

Finally if one subsystem needs to be reactive to another (renderer, physics, audio all need to do stuff when something happens) the components can facilitate this with each other through the game object and keep this particular type of cross system-coupling managable through the components.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ That's good. But how components know about GameSubsystems? Are all subsystems singletons? That's not ugly?... I'm thinking about another solution like dependency injection... but when and who passes the subsystem instance to each component? \$\endgroup\$
    – Dani
    Commented Apr 24, 2011 at 8:52
  • \$\begingroup\$ @Dani Components don't need to access directly to the subsystem instance, they just need to send a message asking for the registration to be done, they don't need to know what the Subsystem is (but they will most likely) And why would they be singletons? That's not a requirement, even if in most cases you will only need a single subsystem instance for each subsystem. \$\endgroup\$ Commented Sep 3, 2011 at 4:03
  • \$\begingroup\$ @Pablo - agree. \$\endgroup\$
    – Rick
    Commented Sep 10, 2011 at 6:03

You must log in to answer this question.

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