Object Creation with Data-Driven / Component-Based Entities?

Started by
11 comments, last by thefries 14 years ago
Hey all, I've been doing some reading lately and noticed the new trend towards component-based entities and I definitely see the power behind making the switch. I have a lingering question though: How are the objects created? Say you define your entities as such (ala Trefall)

<object type="Robot">
  <components>
    <component>Examine</component>
    <component>Movement</component>
  </components>
  <properties>
    <property name="Description">It's a useless robot!</property>
    <property name="MovementSpeed">50.0</property>
  </properties>
</object>
You can't possibly parse the XML every time you want to create a new entity. The only thing that pops into my head is that you create a list of all possible entities with their base values and then deep-copy / clone those entities as you need to create new ones? This could become a problem with very large games though. Re-using entities also becomes a problem, but I imagine you could just store the original values and a reset() method goes back and changes them all? Any insights?
Advertisement
I too have been working on component based entities.
The way i handle this atm is through an intermediate object.
The XML is parsed into an intermediate data graph, which is basically a treemodel in the form of simple name/value pairs.

You can create this graph from either an object or from XML, and the graph can return an instance of the object or translate back to XML.

This is also how i handle deep copies. I first create the graph from the orig. object and then use it to return an instance.

With a little bit of work this could be used to persist the graph and incorporate it into a network layer or field based replication in an object database.

There are other benefits of this, for example handling circular references and reference sharing (both in the XML and in the graph).
Quote:The only thing that pops into my head is that you create a list of all possible entities with their base values and then deep-copy / clone those entities as you need to create new ones? This could become a problem with very large games though.
This is basically what I do.

What sort of problems would you run into using this method for larger games? (I'm not saying there wouldn't be any - I'm just curious as to what sort of problems you have in mind.)
Quote:Original post by GroZZleR
I've been doing some reading lately and noticed the new trend towards component-based entities


This new trend is already around eight years old :D

Quote:Original post by GroZZleR
The only thing that pops into my head is that you create a list of all possible entities with their base values and then deep-copy / clone those entities as you need to create new ones?


Pretty much exactly what I do. When I read in entity definitions, or "templates", I add them to a cache. When I need an entity, I deep-copy the template's components, but I give the new entity an empty property list which points to the original template's property list, thus making it possible to "inherit" properties and avoid property duplication. When an entity is asked for a property that doesn't exist in the list, it will ask the parent list if there is one.

Quote:Original post by GroZZleR
This could become a problem with very large games though.


Only problem I can think of would be storage space for all the referenced data, such as textures and models. However, you can just lazy load expensive data like that. Currently I use proxy objects to load textures when they are first used, and will likely also do that for mesh data later on. If even keeping all the templates in memory is too expensive, you can also defer loading of templates themselves.
Looks like cloning is probably the way to go -- in hindsight I suppose keeping a few extra unused entities of a few kilobytes isn't such a big deal.

Thanks guys.
Quote:Original post by GroZZleR
Looks like cloning is probably the way to go -- in hindsight I suppose keeping a few extra unused entities of a few kilobytes isn't such a big deal.

Thanks guys.


Especially if you compare the sizeof() an entity instance to, say, the length of the file that specified it. :)
Making a clone of an entity doesn't sound like a good idea to me. The proper way to do this is using that good old idiom, instancing. Your xml file there defines an entity "Base" which contains everything about how that entity looks, acts, animates, sounds, etc. Then you create entity instances of that base. each instance doesn't need to store what models, sounds, etc. it uses, it just stores a pointer to the base object, and then has access to any information that it needs. The entity will also have to store any instance data that the base's components require. For example, if you have a "world object" base-component in the base type, then the entity needs a "world object instance" instance-component, which will store the current position of that entity instance.

So your entity has a component instance hierarchy that looks the same as the base, for every base component in the entity base, there is the equivalent instance component in the entity instance and any instance state data goes into the instance components, and any descriptor data goes into the base components.

Hope this makes sense and is somewhat useful.
Quote:Original post by thefries
Making a clone of an entity doesn't sound like a good idea to me. The proper way to do this is using that good old idiom, instancing. Your xml file there defines an entity "Base" which contains everything about how that entity looks, acts, animates, sounds, etc. Then you create entity instances of that base. each instance doesn't need to store what models, sounds, etc. it uses, it just stores a pointer to the base object, and then has access to any information that it needs. The entity will also have to store any instance data that the base's components require. For example, if you have a "world object" base-component in the base type, then the entity needs a "world object instance" instance-component, which will store the current position of that entity instance.

So your entity has a component instance hierarchy that looks the same as the base, for every base component in the entity base, there is the equivalent instance component in the entity instance and any instance state data goes into the instance components, and any descriptor data goes into the base components.

Hope this makes sense and is somewhat useful.


You use somewhat vague wording on a crucial spot "then the entity needs a "world object instance" instance-component". you mean copy it?

I do what people say, except i am not deep copying raw data, only references to raw data (i have a feeling the other people in this thread are doing that too, one would hope).

Also, why are people saying that memcpy is a bad idea? its ridiculously fast, way faster than parsing an xml file. if you load an asset into a class, which describes what makes the object, then clone the asset and add things like position and create instances of things that the object needs on its own (like a collision actor).




------------------------------

redwoodpixel.com

Quote:Original post by AverageJoeSSU
I do what people say, except i am not deep copying raw data, only references to raw data (i have a feeling the other people in this thread are doing that too, one would hope).

Also, why are people saying that memcpy is a bad idea? its ridiculously fast, way faster than parsing an xml file. if you load an asset into a class, which describes what makes the object, then clone the asset and add things like position and create instances of things that the object needs on its own (like a collision actor).


You're contradicting yourself, if you're using memcopy that implies copying all the data, not just using a reference to the data.

This is kinda how I envision the data layout, except it would be more dynamic, using arrays of components instead of the way im doing it here. I'm not using arrays so that you can see exactly what the entity has in it in terms of components.
class cComponentBase{};class cComponent{    cComponentBase *mMyBase;};class cWorldObjectBase : public cComponentBase{    cModel *mMyModel;};class cWorldObject : public cComponent{// implicit->  cComponentBase *mMyBase; <- tells you what model the object uses    cVec3 mMyPosition;    cOrientation mMyOrientation;}class cPhysicsBase : public cComponentBase{    float mMyWeight;};class cPhysics : public cComponent{// implicit->  cComponentBase *mMyBase; <- tells you what the weight is    cWorldObject * mMyWorldObject; // physics component REQUIRES the entity to have a world object component.    cVec3 mMyVelocity;    cVec3 mMyAcceleration;    cVec3 mForces;    void Update ( ); // Updates position, velocity and acceleration for the entity}// this is an entity base that has a world object and physics components (usually more data driven than this - using arrays of components etc.)class cEntityBase{    cWorldObjectBase *mWorldObject;    cPhysicsBase *mPhysics;}// this is the matching entity instanceclass cEntity{    cEntityBase * mMyBase;    cWorldObject *mWorldObject;    cPhysics *mPhysics;}


this is just the rough idea and nothing too specific, but should show you how i separate bases and instances. You make 1 entity base to describe a type of entity, and MANY entity instances of the same base. So you can make a base entity called "tree" and then have 1000 instances of that tree. This is a very simple example.
Quote:Making a clone of an entity doesn't sound like a good idea to me. The proper way to do this is using that good old idiom, instancing. Your xml file there defines an entity "Base" which contains everything about how that entity looks, acts, animates, sounds, etc. Then you create entity instances of that base. each instance doesn't need to store what models, sounds, etc. it uses, it just stores a pointer to the base object, and then has access to any information that it needs. The entity will also have to store any instance data that the base's components require. For example, if you have a "world object" base-component in the base type, then the entity needs a "world object instance" instance-component, which will store the current position of that entity instance.

So your entity has a component instance hierarchy that looks the same as the base, for every base component in the entity base, there is the equivalent instance component in the entity instance and any instance state data goes into the instance components, and any descriptor data goes into the base components.
Are you talking about flyweights?

If so, I imagine that would be a reasonable approach, but for a project of modest scope, I don't know that cloning of prototypes in full is a 'bad idea', per se.

Keep in mind that we're not talking about anything silly like duplicating shared resources here; if a component of a prototype holds a reference to a resource (such as a texture, model, or sound effect), then any clone of that component will just get a copy of that reference.

Applying the flyweight pattern will most likely make for a more complex implementation. As for whether there are measurable gains to be had (e.g. memory savings), I imagine that depends on multiple factors, such as how many entities are generally active at one time, and, on average, how much of the data for a single entity is 'static' and how much is 'dynamic'.

Anyway, in summary, I'm not entirely convinced that using flyweights (which I assume is what you're talking about here) is the only 'proper' solution to the problem. That's just my view of it though.

This topic is closed to new replies.

Advertisement