Re: strategies/patterns for composition
Nathan Martz <Nathan <at> doublefine.com>
2006-10-17 03:02:13 GMT
We use a pretty textbook implementation, too, where an "entity" is basically an array of pointers to
components (all of the base class type). Some types of components are very popular (i.e. transform,
damageable), so entities also cache a handful of direct pointers to the most commonly accessed component
types. We shied away from the relational database approach (which I believe Thief used), largely because
it's counterintuitive and a bit cumbersome but also because our model makes it easy to spend a little
memory to get much faster component-on-entity lookups.
After much discussion, we opted to allow only one instance of each type (direct descendent) of component
per entity. In this way, our system is a bit like dynamic multiple inheritance. In the end, the decision
came down to favoring clarity and simplicity over flexibility. While it makes some sense to have multiple
sound emitter components per entity, it's not clear what it means to have multiple physics components
(does it imply some sort of intra-entity transform hierarchy?). It also means that you never have to worry
about getting an array of components back from your Entity::GetComponent() function and other such
syntactical niceities. In our model, if you want to have an entity with multiple lights (like a car with two
headlights), you would have one entity for the car and one entity for each light, usually with a component
on the main entity that has references to the two child enti
ties (in our case, it would be the vehicle physics component).
As in David's system, our entities are a fairly high level "gameplay" concept. Our heavy duty, lower level
systems like rendering, audio, physics, and pathfinding don't know anything about components or
entities. For those systems, the components usually serve to publish data about a specific entity to the
relevant subsystem (i.e. CoRender tells the renderer what mesh to uses the relevant data from the
CoTransform on the same entity). It's a nice division that lets the game systems be fairly
general/flexible without impeding the lower level systems' ability to operate efficiently.
We differ from the system Jon Watte describes in that we have no formal representation of component
dependencies or inputs/outputs. There's no way to generically connect the float of one attribute to the
float of another, but we haven't found that sort of flexibility to be particularly helpful or necessary.
Components simply access properties of other components as necessary (though we actively discourage
unnecessary dependencies). Soft dependencies are handled gracefully if the component doesn't exist,
hard dependencies usually fire off an assert as soon as possible, which is fine, since it's not clear how,
say, an AI component should respond if it's transform was suddenly removed. Tick order is "hard coded,"
but there's a lot of complexity about exactly when and how to use multiple processors, which would be hard
to represent generically with or without components.
One of the issues we've run into with our component model is deciding what should be a component and what
should not be. Part of the problem is a tendency for programmers (especially ones new to the idea) to
over-componentize their systems (like adding a new component when a bool on an existing component would
have sufficed or requiring a component to request that the sound system play a sound). Appropriate
granularity is also a challenge; it's sometimes unclear when a given feature set should be composed of one
component or several. We've developed a few good rules of thumb (avoid bi-directional dependencies,
don't create components just to hold a bit of data, etc), but it's fair to say that we spend a non-zero amount
of time refactoring components as we learn more about the game and how it's parts relate to one another.
Some examples of types of components in our codebase:
* Team membership
* Health/Damage responses
* Various sorts of physics
* Controller (AI or player)
* Various sorts or renderables
* Skeletal animation
From: sweng-gamedev-bounces <at> lists.midnightryder.com
[mailto:sweng-gamedev-bounces <at> lists.midnightryder.com]On Behalf Of David
Sent: Monday, October 16, 2006 5:50 PM
To: sweng-gamedev <at> midnightryder.com
Subject: Re: [Sweng-gamedev] strategies/patterns for composition
I usually use the so called textbook solution with pointers. An entity
contains pointers to different representations, like graphical or physical.
The graphics subsystem maintains it's own list of the graphical
representations (pawns as I call them) and doesn't know about about the
physical representation and thus only knows what it have to know.
When creating a new entity I only instanciate the representations I need
for the object.
I haven't tried to have multiple representations thought but I guess it
would be possible by just adding an additional pointer in the entity.
//*David Sveningsson [eXt]*
Freelance coder | Game Development Student
Jamie Fristrom skrev:
> So - we've all heard "inheritance bad, composition good" - what I'd like
> to know is what are people's favorite strategies for composition, in
> particular with game entities/actors/pawns (or whatever your engine
> calls them)?
> A few things I've seen done for entities in a game:
> Inheritance - a particle system was an entity, a sound emitter was an
> entity, a billboard sprite was an entity, a limb was an entity.
> Entities specified their position and orientation relative to other
> entities (or null for world-space), so you could "composite" (using the
> more general, English definition of 'composition' here) features by
> having them all parented to the same entity with a zero position and
> identity orientation.
> Textbook composition - entity contains a list of pointers to features
> which the entity may or may not have. Features could be meshes, particle
> systems, sound emitters, skeletons, and more. This actually got kind of
> fat, since there were thousands and thousands of entities, so for
> performance there was a base entity that had just the few really popular
> features (like a mesh pointer) and an inherited entity that had many
> more. Something it couldn't do that I imagine you might want is have
> more than one of the same kind of feature - multiple particle systems,
> emitters, etc.
> A more relational database approach - the features were in tables and
> each feature had an "entity id" field. So there was a
> position/orientation table, a mesh table, a sound emitter table, etc.
> (So an ambient sound emitter wouldn't need a position/orientation, for
> example.) To find out which features a given entity had, you did queries
> on the tables looking for that entity's id. I just heard about this
> system, I didn't actually work with it - it turned out to be slow so the
> results of the queries had to be cached. But it could theoretically
> handle multiple features per entity.
> Is there something better out there? And if not, what's your favorite
> and why?
> Jamie Fristrom - www.torpexgames.com <http://www.torpexgames.com> -
> www.gamedevblog.com <http://www.gamedevblog.com>
> sweng-gamedev mailing list
> sweng-gamedev <at> lists.midnightryder.com
sweng-gamedev mailing list
sweng-gamedev <at> lists.midnightryder.com
sweng-gamedev mailing list
sweng-gamedev <at> lists.midnightryder.com