I'm creating a component-based game object system. Some tips:
GameObject
is simply a list of Components
.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:
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
.
Subsystem
searches for Components
of specific types.pro. Better performance than in Approach 1
.
con. Subsystems
still know about Components
.
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*).Component
subscribes to "update" event (sent by GameSubsystem(s)
).pro. Performance. No unnecessary checks as in Approach 1
and Approach 2
.
con. Components
are badly coupled with GameSubsystems
.
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 (data-driven) implementation of Approach 4
?
Thank you.
Vote for the third approach.
I am currently working on component-based game object system and i clearly see some of additional advantages of this approach:
The Component is more and more self-sufficing subentity as it depends only on a set of available subsystems (i presume this set is fixed in your project).
Data-driven design is more applicable. Ideally, this way you may design a system where components are completely defined in the terms of data but not C++.
EDIT: One feature i thought about while working on CBGOS. Sometimes it is convenient to have ability to design and construct subsystemless passive components. When this is on your mind the fourth approach is the only way.