Component Based Entities - What handles the interaction of components?

Started by
5 comments, last by AgentC 13 years, 7 months ago
Hey all,

In a component based entity system you would have a CollisionComponent (bounding box, bounding sphere, whatever). How would you go about handling the collisions of entities in this case?

I've come up with two solutions:
1. When entities are created the gamestate stores a a reference to the CollisionComponent and handles interactions. This is generally more game specific (do entities die when they collide, do they bounce back, etc.). Maintaining all the lists may become cumbersome.

2. Create specific ComponentManagers for specific Components and they handle the logic. This would be less game specific and more general with more events / callbacks. Coding specialized managers for specific components may be overkill.

What's the best way? Is there another way?
Advertisement
Quote:
What's the best way?

There isn't one.

Quote:
Is there another way?

Most certainly.

I have noticed this tendency: the component-based fad seems to blind people to the usual techniques of software design, for some reason. You should approach this problem in the same way you would if you'd never heard of "components."

First, look at the project you're making. Identify what kind of behavior you need out of the collision check/response system. How will that work -- will the physics system handle it? How will that system notify external clients -- events, callbacks? There are many different ways to do this, all valid, none "best" in general. There will be a few that work most smoothly for your project based on your coding style and existing code. Without more information its hard to comment on that.

Build the collision system you want, and then figure out how to adapt it for use in a component-oriented system. Remember, between the two it is the collision system that is more important, so you should design it so that it functions in the most natural way you need. Only then should you worry about components.

I generally prefer to keep all those sorts of subsystems -- collision, scripting, et cetera -- entirely decoupled from the "component" aspects of any given codebase. Components are then written as third-party objects that just enable you to tie together separate systems, or more specifically the appropriate agents of representation in those separate systems (i.e., rigid bodies).
I went the manager route. The base manager just has one method: update(time). It iterates over the components and invokes each of their update(time) methods.
Quote:Original post by jpetrie
I have noticed this tendency: the component-based fad seems to blind people to the usual techniques of software design, for some reason. You should approach this problem in the same way you would if you'd never heard of "components."


Indeed. The ironic part is that "the component-based fad" is just taking one of the usual techniques of software design and giving it more emphasis. (To be fair, it often doesn't get enough emphasis normally.)

It's just composition. You know, that other thing besides inheritance.

:)
Quote:Original post by GroZZleR
Is there another way?
Sure, how about:

The collision manager detects collisions between entities and issues events off to those entities affected. An entity's components then respond to that event however they wish to, e.g. DieOnCollideComponent, ExplodeOnCollideComponent, BounceOnCollideComponent, etc.

Alternatively, components could reference and poll the collision manager with their own collision queries; or upload these queries once and wait to be notified by the manager using events as mentioned above.
The way I do it is have each component type has its own "handler," which calls all the Update() and Render() of each specific component type at once. This way, each "game screen" (or game state, I guess you could say) can have its own special renderers for the entities that need them. All "updatable" components are updated every frame, but "renderable" components are rendered directly by the game screens with which they are associated. Components (and therefore by extension entities) communicate with each other through a "message router", which dispatches messages to particular entities, which then pass those messages on to their sub-components. This message router is associated with a "simulation" object, which contains the a collection of entities that exist within the game universe.

I'll use a typical RTS example to make this arrangement more clear: that of a game unit. A unit typically has an actual graphic that is displayed upon the play field, an overlay displaying health/mana when the unit is selected, and a display in the game UI that has the same information plus (in the case of units that make other units) things like building queues. Now, in my system, each of those specific rendering tasks is modelled by a specific kind of renderer - one for rendering the unit graphic, one for rendering its overlay and one that displays unit stats in the UI when the unit is selected.

With regards to the messaging system, when a unit casts a spell, the UI triggers a message that represents the spell and targets it at a particular entity. Which specific entity gets targeted is determined by the UI telling the simulation object that it wants to cast a spell at a particular location. This is essentially the same as querying the simulation object for an entity or list of entities in a particular spot. This entity or group of entities is then sent a message through the message router, and the spell's effects are realized.

The UI is quite separate from this entire system. That's partially because I'm experimenting with a homebrew immediate-mode UI, but also because I wanted to keep the entity-handling subsystems away from the UI. There's no particular reason why the UI couldn't also be component based using a system like this; it's purely a matter of personal taste.

As to your original question concerning collisions: this is a very rough design, but I would probably model objects that can collide with a PositionComponent (position, velocity), a PhysicalCharacteristicsComponent (mass, size), and a CollisionComponent, which would reference some other, probably simulation-wide, object that handled collisions. Maybe a quadtree or octree, or in the case of the RTS example, probably a tile-based terrain model. Let's go with the latter since it's probably the simpler of those. In that case, upon calling Update(), the Collision component of a unit would query the other two components to make certain that the unit is now in the proper terrain cell. It would update the collision-handling data structure and then see if the unit is colliding with any units in that cell. If there was a collision, it would send a "unit x collided with unit y" message into the message router and then move on to the next unit. Again, this is very rough, there might be problems with this design that I'm not foreseeing.
I like having "active" or "logic" components in the entities that subscribe to events like collision, and tick update. These active components may either directly access components in other entities (leading to tighter coupling -- perhaps not preferable), or send more events in response (more general.)

This topic is closed to new replies.

Advertisement