5
\$\begingroup\$

Well during this week I have deciding about implementation of my entity system. It is a big topic so it has been difficult to take one option from the whole. This has been my decision:

1) I don't have an entity class it is just an id.

2) I have systems that contain a list of components (the list is homegenous, I mean, RenderSystem will just have RenderComponents).

3) Compones will be just data.

4) There would be some kind of "entity prototypes" in a manager or something from we will create entity instances.Ideally they will define the type of components it has and initialization data.

5) Prototype code to create an entity (this is from the top of my head):

int id=World::getInstance()->createEntity("entity template");

6) This will notify all systems that a new entity has been created, and if the entity needs a component that the system handles it will add it to the entity.

Ok, this are the ideas. Let's see if some can help with the problems:

1) The main problem is this templates that are sent to the systems in creation process to populate the entity with needed components. What would you use, an OR(ed) int?, a list of strings?.

2) How to do initialization for components when the entity has been created? How to store this in the template? I have thought about having a function in the template that is virtual and after entity is created an populated, gets the components and sets initialization values.

3) Don't you think this is a lot of work for just an entity creation?.

Sorry for the long post, I have tried to expose my ideas and finding in order other could have a start beside exposing my problems.

Thanks in advance, Notbad.

\$\endgroup\$
4
  • \$\begingroup\$ question - where are the methods? \$\endgroup\$
    – egarcia
    Jan 14, 2011 at 21:19
  • \$\begingroup\$ Is there something wrong with an entity type and it can have a constructor? \$\endgroup\$
    – DeadMG
    Jan 14, 2011 at 22:43
  • \$\begingroup\$ @DeadMG Component systems are made up of multiple objects, each of the sub objects can have a constructor but the object itself doesnt... depending on implementation. A factory to make the object based on a template is the most common method of piecing together component objects. \$\endgroup\$
    – James
    Jan 14, 2011 at 23:09
  • \$\begingroup\$ @egarcia Methods are hold in the systems. Components will just contain data. This is good for example to get tight loops, because you have a system with just one method to process a list of components... Good caching!. Anyway it is not all good, there are some foes like in any other design. \$\endgroup\$
    – Notbad
    Jan 15, 2011 at 10:07

2 Answers 2

5
\$\begingroup\$

Hey again NotBad, lets see if I can give you a hand again :)

1) EDITED. If you have alot of common components then pre-making a set of them could be very helpful in increasing the speed of creation and deletion. In previous component systems I have used all of the components were tied together with a single ID for example. So to 'allocate' a component to a specific object you would just give it the id of the object it belonged to. To 'deallocate' the object you would remove the id or set it to -1 or some other value to mark it as Unused. This way you only ever allocate memory on startup or when you run out and need to make another handful of a specific type. Deallocating would basically only be done at the end of the game's runtime.. You would eventually want to put in some sort of balancing routine that if you have say 15 unused components in a pool of 30 of that type that it dumps a certain number of them down or the like.. What you DO have to be careful of with this setup though is memory fragmentation.. If you are working within a managed system this should not be a concern, but just in case you are not be aware of that. Hope this helps answer the question a little better :)

2) As eluded to in the first one, you may want to include default values in the templates, this would set up their initial values when they are created (Read in a component, add it to the object in whatever tethering method you are using for your component system and then give it the values supplied by the teamplate). If I recall you are using Lua in here. If the object is represented in Lua after you call the sample CreateEntity() method you may want to return a Lua object that represents the object (even if in C/C++ it is just unified by Id). You could then just set the values directly via the object reference. This may be a bit more work in translation and such between the two systems but I can almost guarantee the payoff will be there in the long run.

3) EDITED. All in all some of the slowest execution speed in what you are doing here is going to be memory allocation. Having a good method as touched upon in the first answer can be key to this. Using a pooling system as described above can be very nice especially in a component system.. if you have a component that moves entities then you can use the same one for a positional sound effect, a particle effect, a player character, etc.. All it does is hold a position and functions for movements. Reuse-ability of component based systems along with their wide instead of tall structure a just a few of the benifits you can get :) For example, the engine I was working in professionally a few years ago was capped to say 100 objects for an entire level, I made a pooling/spawning system to make it 100 objects at a time.. now a PSP can not render that many objects at once, but it freed up the designers to really go wild and make the levels more interactable :) Back on topic, if you can allocate and deallocate all your memory on 'loading' screens (Yes, giving away knowledge that generally the first thing done on Loading screens in games is Unloading data) you will have much smoother game play sessions.

So again, hope I have helped as much as I thought I did on your first set of questions and good luck!

\$\endgroup\$
10
  • \$\begingroup\$ Hi James! Thanks a lot for your time again. In 1 I wasn't asking how to represent the template to be loaded (I decided like you to do it through XML, or just with a creation function in LUA, sorry If I wasn't clear), but how to manage this data in memory eficienly to quicly create the requested entity. One solution I have come with, is at loading time, create the templates that will contain instances of the components they will have and when requesting a new entity just use the copy constructor of the real component to clone it with the one in the template. What do you think? \$\endgroup\$
    – Notbad
    Jan 14, 2011 at 23:45
  • \$\begingroup\$ I added another comment because I needed some more space. James when I said that it was a lot of work I was refering to all the things the system has to do to create an entity or delete it. When creating, we have to get the template send it to the systems (all, I don't know how many system could be, but I guess a lot for every aspect of the entity), then the system decide if it has a component it is interested, instantiate it, and init it, etc... Don't know if this will slow down things, anyway, deletion and creation won't happen a lot of times each frame. \$\endgroup\$
    – Notbad
    Jan 14, 2011 at 23:50
  • \$\begingroup\$ Hi!, yes James you helped out as allways. I had in mind to add a pooling system per system too as you stated, just, now I'm justg more aware of the design. One of the nice things about having components per system is that they hold a homogenous list or whatever TAD that is pretty easy to pool, loop, etc... So, rewritting my thoughs to clarify: From the xml (or a template build in lua and registered to C++) we create entity templates that it is just, a list of pre created and initialized components (componets know how to load themselves from xml). "Continues next chunk" \$\endgroup\$
    – Notbad
    Jan 15, 2011 at 8:27
  • \$\begingroup\$ (resuming) When we want to create an entity this template is passed to systems, and they check for the components they care and take out a free component from its own pool and clone from the one that comes in the template and registers it in a used list or whatever. When an entity is deleted, the id of the entity is given to systems, they flag components as dead, and in a later iteration (end of frame) they return to the pool. I think this is the way I could do it. What do you think? \$\endgroup\$
    – Notbad
    Jan 15, 2011 at 8:31
  • \$\begingroup\$ That does not sound too bad for me and I think is a good place for you to further your progress on your engine :) \$\endgroup\$
    – James
    Jan 16, 2011 at 21:14
1
\$\begingroup\$

1) Your question sounds like "What type should the template identifier be", but seeing your comment on James' answer I think you're actually asking "How should templates be stored to make creating instances fast". It sounds like your entity template is basically a set of component templates, which themselves basically are instances of components. So, when you register these entity templates (either in code or by loading from a file), you'd just go through each component template in the entity template, look up the system by name (the components will need some kind of identifier, e.g. "Renderable"), and give that system the entity name ("Alien") and the block of data that makes up that component template.

If doing this at runtime, you can just construct a component and pass it along as that type (e.g. RenderSystem->register("Alien", AlienComponentData(1,2,3)); ), or if loading in from a file you can either pass in binary data for the system to just memcpy, or xml data for it to parse.

2) Carrying on from my answer to 1), just copy the template, which is an instance of a component (just not one that's active in the game). Then add that to your set of active components, with its entity id set. Nice and fast.

3) Not really, these things have to be done somewhere! In traditional inheritance-based entity structures it's just harder to see. Creating an entity by just copying some memory is going to be pretty slick, especially if you're copying it into already-allocated space inside a pool.

I hope I've understood, and I hope my answers are what you were expecting :)

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .