Basic Component Based Entity

Started by
67 comments, last by crancran 12 years, 5 months ago
I like the spacial database idea a lot. I can see it being helpful for culling and deactivation purposes as well. A majority of my entities won't really need a lot of vitals. The enemies really only need health since their speed and attack will probably be handled via the AI component's external scripting.

If this method works out like I think it will it'll be a lot cleaner than my current system which has separate managers for enemies, props, etc. I'm trying to work on my ability at OOP design and thinking while not overdoing it. I don't like inheriting to get entity types.

Now when having my other components communicating with the SpatialDatabase should I do so by events, make it a singleton, or pass it by reference to the individual systems?
Advertisement
On 11/2/2011 at 2:36 PM, jaeg said:

I'm trying to work on my ability at OOP design and thinking while not overdoing it.

Actually, the whole Entity-Component paradigm is a move away from object oriented, to "data oriented" (although that name doesn't exactly capture what it is we're breaking out into components, or why). But the point is that there is too rich a set of possible object types and features to conveniently characterize them all as specializations of each other, or to share features accurately via inheritance. So the object oriented approach breaks down.

In other words, organizing your design around using programming language objects to represent game world objects doesn't work. So we're organizing our design around using programming language objects to implement game world object features instead.

(Which doesn't necessarily eliminate the use of programing language objects to represent game world objects. It just allows for the possibility. But when it doesn't, those resulting objects end up looking and working quite different due to the design approach.)


Since all those other components depend on entity position, rather than each of them making the sub-system look it up every frame, you might opt to have them each cache a reference to it. In fact it's probably a good idea for each of them to verify its existence when they're created, since they can't work without it.


Following the premise that we use a caching mechanic, when entity 123 is created from it's template, the template dictates that two components are necessary; position & render. The entity system will invoke the two subsystems for position and render to create their respective components for entity 123. But if the position component is listed after the render component in the load process; how then do you handle your render component getting the position from the spacial subsystem? Is this handled by having an interface defined for each component so that as you create each component for an entity, you store each component in a temporary list, then iterate each of them calling some virtual method such as OnInitialize() after each component has been allocated so they sync up prior to returning a success create for this entity?

How would you handle the notion of removing a component attached to an EntityID that another component depends upon and already has a reference to? I don't want that render component to continue holding that position reference (although bad example) and then that position component be reused for another entity latter and now all my pointers are being mix-matched.
On 11/2/2011 at 3:18 PM, crancran said:

But if the position component is listed after the render component in the load process; how then do you handle your render component getting the position from the spacial subsystem?

If order matters, then you'll probably have to get it right. If the render component expects a position component to exist, then the tool must generate a position component before a render component.

If you don't want it to matter, there are many options. For example, you could implement some sort of lazy handle. So the render component would have a handle to the position component, and when it was used, it would look up the position component if it hadn't already. Or you could just not cache it at all, and look it up every time. In either case, rather than verifying at creation, the system blows up if the position component is missing the first time the render component tries to get it.

On 11/2/2011 at 3:18 PM, crancran said:

How would you handle the notion of removing a component attached to an EntityID that another component depends upon and already has a reference to?

It should be noted that just because component systems don't result in compile time entity definitions and entities are built at run time, doesn't mean that they ought to be used to implement dynamically morphing entity types. That's not really the main point of using a component based design. In other words, a component based entity system doesn't necessarily need to support arbitrary removal of a sub-set of an entity's components.

Dynamic structure building (e.g., creation of a squad object which controls a group of units, etc.) can be done on another level, designed to manage entity relations. Similarly sub-component structure building, (e.g., AI sub-objects which create and manage each other), might best be handled with a system specific to that. And again, an attachment system, for use with animation or physics, should probably also be implemented separately.

But if you were to support dynamic component changing, obviously removal of a requisite component would still be an error. So the simplest answer is, don't cache references to components that will be removed (although everything still blows up if the component is still missing next time you try to use it). If that's too ad hoc for you, then you need to develop a system of component relations, probably using some sort of smart handles.

Also, if the make-up of an entity can change over time, then you'll probably want an entity object to track that, to facilitate destruction of all the correct component objects at entity expiration (unless its acceptable to attempt component removal on all engine sub-systems).

Just a word of caution: Don't get too crazy with creating a component for every little thing. You will end up with an application so complicated and with so many little pieces it will become impossible to manage. Creating entities will be tedious because you'll be adding six components when one Stats component would do. Remember, some of the primary reasons to avoid inheritance is to reduce complexity and improve manageability. Having to select from 200 different components just to create some trash enemy will be the complete opposite of simple and easy to manage.

[quote name='crancran' timestamp='1320272283' post='4879895']How would you handle the notion of removing a component attached to an EntityID that another component depends upon and already has a reference to?

It should be noted that just because component systems don't result in compile time entity definitions and entities are built at run time, doesn't mean that they ought to be used to implement dynamically morphing entity types. That's not really the main point of using a component based design. In other words, a component based entity system doesn't necessarily need to support removal of components.
[/quote]

So when a mob is killed in the game, there are some a small number of components that may drive the entity's behavior at that point. If the mob had an AI component to control certain aspects of it's behavior, upon death that AI component does nothing. So this AI component just remains in the AI subsystem's component vector list until the entity is removed by the corpse subsystem?

Just a word of caution: Don't get too crazy with creating a component for every little thing. You will end up with an application so complicated and with so many little pieces it will become impossible to manage. Creating entities will be tedious because you'll be adding six components when one Stats component would do. Remember, some of the primary reasons to avoid inheritance is to reduce complexity and improve manageability. Having to select from 200 different components just to create some trash enemy will be the complete opposite of simple and easy to manage.


Isn't this where being able to build templates in the game editor would play a vital role?

Just because I give the designer 200 components doesn't mean they need to select those 200 each time they want to add an entity to the scene. I would imagine the game editor tool should allow the designer to pick and choose from those 200 components and build pre-fab entity templates that can also be inheritance based. This way if they change a combination at a parent level of the entity template hierarchy, all child templates would reflect the change. Is this not a common approach for game editoring/authoring tools?
On 11/2/2011 at 4:21 PM, crancran said:

So when a mob is killed in the game, there are a small number of components that may drive the entity's behavior at that point. If the mob had an AI component to control certain aspects of it's behavior, upon death that AI component does nothing. So this AI component just remains in the AI subsystem's component vector list until the entity is removed by the corpse subsystem?

That seems reasonable. The AI could know how to act when the entity is dead (and that could even involve changing the internal makeup of the AI component, dynamically). Another option might be to replace the entire entity with a corpse which has the components it needs.

Ok brace yourselves for a possibly horrible idea.

This is an idea on how to create communication between subsystems. Create a vector that contains Event structures and pass this vector to each subsystem through the update function. If it's something solely AI specific remove the event after the AI system updates. Do the same for the other events. At the end up the game loop empty out the event vector.
Horrible, bad, ok?


When my AI controlled entities die they are going to just fizz out (the game takes place in a virtual reality type thing) and after that's done I'm just going to remove the components from the systems based on the entity ID.

[quote name='crancran' timestamp='1320276091' post='4879927']
So when a mob is killed in the game, there are a small number of components that may drive the entity's behavior at that point. If the mob had an AI component to control certain aspects of it's behavior, upon death that AI component does nothing. So this AI component just remains in the AI subsystem's component vector list until the entity is removed by the corpse subsystem?

That seems reasonable. The AI could know how to act when the entity is dead (and that could even involve changing the internal makeup of the AI component, dynamically). Another option might be to replace the entire entity with a corpse which has the components it needs.
[/quote]

That is a thought, but then I question it's viability. Your corpse system would need to be notified upon death of an entity, easily triggered by the vitals system. The corpse system could query each of the subsystems that are necessary to create a "corpse" and get that entity's component's and create a copy of them but under the new entity id. Afterward the old entity's components could be removed and added to the object pool, allowing the render phase to display the corpse and conserve resources for game loop iterations too.

I am still stumped on the life-cycle process however...

At the beginning, an entity needs to be created and so the entity subsystem inspects the template for that entity and determines the components needed. Since components and subsystems are registered in a factory with static create methods, the entity manager can easily create those objects by calling the appropriate static functions and passing the entity id. Those subsystems will create their various components and then after that process, a "sync" step occurs so that all those components created can get references to one another. But when it comes time to remove an entity id from the entity system, how can I tear down these components and their relationship to an entity id? Do I just look over all subsystems that are in the subsystem registry and notify them that entity ABC should be removed?

This topic is closed to new replies.

Advertisement