Sign in to follow this  
Viperfourfive

Problems understanding Entity Component Systems

Recommended Posts

I have a rather long list of material (source-code, blogs, articles, powerpoints, stack-exchange posts, etc) that I've read on the topic, and I feel like I  have a good understanding of why using a structure like this is beneficial.  However, in practice I'm having a hard time implementing it.  I know that:

  • Entities - Should only be an id.  AND that it should contain a list of components that link to that id.  Basically, "bagging" components that would represent and object in the game world.
  • Components - Should only be data.  Ie.  A position component in a 2D game would represent the Vector2 values for X & Y. Renderable component would be a bool value, allowing the objects position to be passed to the rendering system.
  • Systems - Are just methods containing game logic.  Ideally, operating in loops, and processing similar data before moving to the next method. Ie. processing all physics data for all "active" entity id's, before moving to the render method.  Doing this help increase cache coherency. 

My problem, is that I'm having trouble applying these concepts into the basics of basic; Hello World.

Part of my problem, is that alot of the guides and code I've read are in C++ or Java (which I don't really know) and I'm using C# to take advantage of XNA/Monogame.  For instance, most of the C++ examples use pointers to reference the component class.  

Component* component = Component[num_components]; 

From my limited knowledge of C#, pointers are basically useless.  Unless you want to mark it as "unsafe" and flag it that way to everyone that runs the app.  So, what should I be using instead of these?

 

Digging into the source code for the C# ports of Artemis & Ash seem bloated with extra features.  Because of this, I'm having a hard time understanding exactly what methods are actually required and where to draw the line.  I realize that this system is complex and requires a bit of "start up overhead", for lack of a better term.  But, to me, that shouldn't mean that I need Managers for each one, right? 

Another thing I don't understand is that source code examples (from many languages), pass Component component (Class/name - respectively), like:

public void AddComponent(Component component)
{
   //do stuff
}

However, they never actually instantiate "Component" anywhere in Entity.cs.  How does it know to pass this value correctly??
 

I'll be honest, I have no intentions of building my own engine, and I think Artemis is eventually what I'll be using for my project.  However, I feel that in order to use such a system, one should at least understand the basic principles that make it work; to me, not doing so is a very serious mistake.  I feel that if I just keep reading the same articles on this I'm not going to get anywhere.  Can someone help point me in the right direction?  

   

Edited by Viperfourfive

Share this post


Link to post
Share on other sites

For instance, most of the C++ examples use pointers to reference the component class.  
Component* component = Component[num_components]; 
From my limited knowledge of C#, pointers are basically useless.  Unless you want to mark it as "unsafe" and flag it that way to everyone that runs the app.  So, what should I be using instead of these?

 

The equivalent in c# is a reference type (e.g. a class instead of a struct). The end result is the same - you're passing around a reference to the component, not a copy of it. So as long as your components are classes, not structs, you'll be fine.

 

The problem is that - to minimize cache misses - you want the components of a certain type contiguous in memory - which you can only guarantee in C# if you use value types (structs). So in C#, if you're using reference types (which you pretty much have to), your component arrays will references to objects which exist "elsewhere" on the heap. In practice, objects of the same type allocated on the heap sequentially tend to end up in contiguous memory anyway, so it may not be a big problem.

 

I talk about this a bit in the Memory Layout section of this post:

https://mtnphil.wordpress.com/2013/03/27/entity-component-system-architecture-c/

 

 

 

 


 But, to me, that shouldn't mean that I need Managers for each one, right? 

 

Are you talking about the "component manager" thing in Artemis? That's used simply to manage an array of a particular component type. These arrays need to be stored somewhere. Some people store them in the systems. So a system would "own" a certain component type (or types). I don't like that design, as there are several component types (such as position) that don't make sense to be "owned" by a particular system. Does that make sense?

 

 

 

 


Another thing I don't understand is that source code examples (from many languages), pass Component component (Class/name - respectively), like:
public void AddComponent(Component component)
{
//do stuff
}
However, they never actually instantiate "Component" anywhere in Entity.cs.  How does it know to pass this value correctly??

 

Well whomever is calling this method has already instantiated the component in question. And Component is just the common base class for any component. I'm not quite sure what you're asking?

 

I don't have anything like this In my implementation. Instead, I have pre-allocated arrays of each component type (each type in a ComonentManager instance). Code calls into the entity manager and asks "allocate a component of this type for this entity". Based on the type, we call into the appropriate ComponentManager and tell it to reserve an already-allocated component for us, which we then associated with the entity.

 

If you're interested, you can see a slightly older version of my ECS in the source code attached to my bomberman article: http://www.gamedev.net/page/resources/_/technical/game-programming/case-study-bomberman-mechanics-in-an-entity-component-system-r3159

Edited by phil_t

Share this post


Link to post
Share on other sites

The equivalent in c# is a reference type (e.g. a class instead of a struct). The end result is the same - you're passing around a reference to the component, not a copy of it. So as long as your components are classes, not structs, you'll be fine.
 
The problem is that - to minimize cache misses - you want the components of a certain type contiguous in memory - which you can only guarantee in C# if you use value types (structs). So in C#, if you're using reference types (which you pretty much have to), your component arrays will references to objects which exist "elsewhere" on the heap. In practice, objects of the same type allocated on the heap sequentially tend to end up in contiguous memory anyway, so it may not be a big problem.
 
I talk about this a bit in the Memory Layout section of this post:
https://mtnphil.wordpress.com/2013/03/27/entity-component-system-architecture-c/

Good, I think I'm in the right frame of mind here.  I'm using classes for each of my components currently, all of which inherit from a "BaseComponent".  Unfortunately, I'm unsure what to put in the BaseComponent, besides: uint id; and string name; which after reviewing your component class seems wrong.  You have abstract classes (with only methods, no variables..). After a bit of reading today I was planning to use Interfaces in my baseComponent class and give it an Update(). To my understanding, derived classes need to have the same methods as the interface; and they both (abstract and interfaces) seem to be doing the same thing here.  Is there a right or wrong way here or just style? 

Honestly, I don't think my game will run into performance issues, due to it being so small.  I just want to get some practice in learning ECS > OOP. Thus, I think using reference types over value types shouldn't be a big deal.

 

 

Are you talking about the "component manager" thing in Artemis? That's used simply to manage an array of a particular component type. These arrays need to be stored somewhere. Some people store them in the systems. So a system would "own" a certain component type (or types). I don't like that design, as there are several component types (such as position) that don't make sense to be "owned" by a particular system. Does that make sense?

In a sense, yes, but Artemis has an Entity Manager, Component type manager, system manager, etc (look in the manager folder, they have tons).  I also don't like the idea of having any system own a component type.  To me, all data should be stored in the components themselves; with no methods.  And the systems should have all the methods, with no data.  

But that's what I don't understand, if the components are separate from the systems, why do we have the managers?  Shouldn't you just be invoking calls to the specific system that matches the component?

 

 

Well whomever is calling this method has already instantiated the component in question. And Component is just the common base class for any component. I'm not quite sure what you're asking?
 
I don't have anything like this In my implementation. Instead, I have pre-allocated arrays of each component type (each type in a ComonentManager instance). Code calls into the entity manager and asks "allocate a component of this type for this entity". Based on the type, we call into the appropriate ComponentManager and tell it to reserve an already-allocated component for us, which we then associated with the entity.
 
If you're interested, you can see a slightly older version of my ECS in the source code attached to my bomberman article: http://www.gamedev.net/page/resources/_/technical/game-programming/case-study-bomberman-mechanics-in-an-entity-component-system-r3159

Actually, I think you answered it.  They don't have to instantiate in "Entity.cs" or where ever.  Because the method doing the calling (typically in the game loop) is already instantiated.  It then, is just passing the variables it needs along to the correct classes method.  Did I understand that right?

 
I feel like there is still a bunch questions I need to ask, but before I do I want to re-read your BomberMan article.  However, I do want to ask one more question.  You use {get;set;} alot in your Components, is this becuase you're just pulling the data from your "prefab" or templates?  Is there anything wrong with just leaving the values hard coded into each component?  And instead of using prefabs just creating a new component with the new values you want?  Is using the prefab really that much faster and what are the benefits?

Thanks for getting me one step closer to understanding this, I really do appreciate your time.  

Edited by Viperfourfive

Share this post


Link to post
Share on other sites


Unfortunately, I'm unsure what to put in the BaseComponent, besides: uint id; and string name; which after reviewing your component class seems wrong.

 

My Component class (for the Bomberman article) just contains what it needs - which is actually nothing. In fact it should really be just a C# interface, not an abstract class (I used to have id and type in there, but realized I didn't need them). If you need id and name in your BaseComponent class, then go ahead and put them there (I would really question the need for name, though). I was able to structure my code so that those were unnecessary. 

 

Most of the methods on my Component abstract class are for serialization; if you want to save the state of the world (e.g. for save game), each component needs to know how to serialize itself. The "template" stuff is for checking if a component has different data than the prefab for the entity it belongs too. It's an optimization for reducing the size of the serialized world state. So I would ignore all that stuff if you don't need it. The only thing I really need is the Init() method which resets the state of a Component to its default values. Sort of like a constructor would do - but since these components are already pre-allocated, I can't invoke the constructor. So I call Init() whenever I reserve a component for an entity.

 

As for adding an Update() on component, that's kind of in conflict with the notion of systems (used in Artemis and other ECS's). The systems should contain the logic to operate on components. Components themselves are mostly just dumb property bags. I'm not saying having Update() on components is wrong (for instance, Unity's components work like this), but in that case you wouldn't need the concept of a system. You would also have the following drawbacks (which may or may not be important to you):

    - Update is a "black box" (traditional OOP would say this is a good thing) - the calling code doesn't know what the component might be doing - what state it might be touching. This makes it hard, for instance, to parallelize processing large amounts of components if you want to support using multiple cores

    - components will now have dependencies on other objects. For instance, the rendering component would need to access the renderer code in order to draw itself. All this does is increasing coupling between different parts of your code.

    - components will now have dependencies on other components and need to "talk to them". For instance, most components will need access to the position component to do anything useful. If logic were instead in the System, then it is the System that has knowledge of the render and position components. The render and position components wouldn't know anything about each other

    - each component would be doing its work in isolation. This makes it more difficult to write code that reasons about sets of components; for instance if you need to reason about components based on their location in the game world

 


But that's what I don't understand, if the components are separate from the systems, why do we have the managers?  Shouldn't you just be invoking calls to the specific system that matches the component?

 

It looks like Artemis has changed quite a bit since I last looked at it, so I'm not sure exactly what the various classes do.

 

The general pattern should be:

- The EntityManager (or EntityWorld or whatever), is told to Update()

- This calls the SystemManager.Update()

- SystemManager just runs through each system (in a very specific order - i.e. you need to be careful about the order in which your systems are updated) and tells it to Update()

- Each system is then responsible for processing the entities it's interested in. e.g. the RenderingSystem would process all entities that have both a RenderComponent and PositiionComponent, and make the necessary draw calls to draw them.

 

 


 To me, all data should be stored in the components themselves; with no methods.  And the systems should have all the methods, with no data.  

 

I think it's fine if systems have some data. But all persistent game data should be in the components. But for instance, my PhysicsSystem would contain the data it needs to interface between the physics library I use, and the game entities. Neither the Farseer physics library nor the PhysicsComponent know anything about each other, so my PhysicsSystem is responsible for knowing which Farseer Body object corresponds to which of my PhysicsComponents.

 

 


You use {get;set;} alot in your Components, is this becuase you're just pulling the data from your "prefab" or templates?  Is there anything wrong with just leaving the values hard coded into each component?  And instead of using prefabs just creating a new component with the new values you want?  Is using the prefab really that much faster and what are the benefits?

 

get; set; is just syntactic sugar for C# properties. Looking at my bomberman code, I could just as easily have made these fields instead of properties. There are only a few places where I need properties. For instance, in the Placement component, when the Position property is set, I need to set a dirty bit too. The use of properties instead of fields has nothing to do with prefabs.

 

Prefabs are totally optional. You can just wire up entities manually in code if you like. I actually see that in my ECS, I *only* support creating prefabs. But if I supported creating entities directly in code, it might look something like:

        private Entity MakeSpaceship(EntityManager em, Vector3 spaceshipPosition)
        {
            Entity e = em.AllocateEntity();
            bool allocatedNew;
            Placement placement = (Placement)em.AddComponentToEntity(e, ComponentType.Placement, out allocatedNew);
            placement.Position = spaceshipPosition;
            Aspect aspect = (Aspect)em.AddComponentToEntity(e, ComponentType.Aspect, out allocatedNew);
            // etc.... 
            aspect.ModelNameId = SomeFunctionToGetTheSpacehipModel();
            Physics physics = (Physics)em.AddComponentToEntity(e, ComponentType.Physics, out allocatedNew);
            physics.IsDynamic = true;
            physics.BoundingVolumeType = BoundingVolumeType.Circle;
            // etc...
            return e;
        }

Now, you might need the entity to be in a special "creation phase" while you're setting properties on its components - that is, the systems wouldn't officially know about it yet. Then once you're done setting the values in its components, you say "I'm done", and the entity is officially added to the world. I think one reason I *only* allow prefabs is so that I didn't need to support a special creation phase - or rather I do, but it's hidden inside the EntityManager, and calling code doesn't need to be aware of it.

Share this post


Link to post
Share on other sites

The only thing I really need is the Init() method which resets the state of a Component to its default values. Sort of like a constructor would do - but since these components are already pre-allocated, I can't invoke the constructor. So I call Init() whenever I reserve a component for an entity.

Crystal clear.
 

 

As for adding an Update() on component, that's kind of in conflict with the notion of systems (used in Artemis and other ECS's). The systems should contain the logic to operate on components. Components themselves are mostly just dumb property bags. I'm not saying having Update() on components is wrong (for instance, Unity's components work like this), but in that case you wouldn't need the concept of a system. You would also have the following drawbacks (which may or may not be important to you):

Yeah, which I think I recall myself saying I liked when systems and components separate themselves.  I guess OOP habits die-hard, and since I'm trying to say with an ES model I definitely want to stay away from this.

 

 

The general pattern should be:
- The EntityManager (or EntityWorld or whatever), is told to Update()
- This calls the SystemManager.Update()
- SystemManager just runs through each system (in a very specific order - i.e. you need to be careful about the order in which your systems are updated) and tells it to Update()
- Each system is then responsible for processing the entities it's interested in. e.g. the RenderingSystem would process all entities that have both a RenderComponent and PositiionComponent, and make the necessary draw calls to draw them.

So, the SystemManager is really just a class that calls all of the other systems, sort of a fail-safe.  So, that one does not render before updating the position of a sprite; or something similar.

Which really only leaves me with questions regarding the Entity class itself.  At the very least I think all I need and id, a container for the components(for each id), an add function, and a remove function.  So I need:

  • to instantiate Entity in my main
  • use it to call _e.AddComponent(new component(position));
  • repeat for all component for each ID.  
  • use _e.Remove();  when something is deleted from the game world.  

Does this sound about right? It doesn't to me, because I'm not using to ID to assign any sequential ID's.  It seems like I want to use a dictionary<> to link the id "key" to the component list "value"?

Share this post


Link to post
Share on other sites

After re-reading through a bunch of articles, I came across this again; which lead me to the source code on github.  Going through this again answers my questions from the OP on "What is the bare minimum required"?  However, there is a few things I need clarification understanding.

In the EntityManager, he defines (in Java)

HashMap<Class, HashMap<Integer, ? extends Component>> componentStores;

My very limited knowledge of Java means this should convert to C# like:

Dictionary<??, Dictionary<uint, IBaseComponent>> componentStores;

Now, I cannot say "class", intellisense doesn't allow it.   But is there anything wrong with using "Object"; it's the base class of all classes.  Or do I want to continue to use my empty interface "IBaseclass" that all of my components inherit from? 


*edit* Also, my original thought was to use the following:

Dictionary<uint, List<IBaseComponent>> componentStores;

This way, when an entity expires, I can kill it and all values assigned to it, by just freeing the key using the uniqueID I've given to it.  I don't see the benefits to storing the nested dictionaries<>;  if someone knows why I would definitely want to hear why.

Edited by Viperfourfive

Share this post


Link to post
Share on other sites

So it looks I was looking for something like the following...  Since There is no direct conversion for "?" in C# from Java.

System.Type type = typeof(className);
 &
objectName.GetType();

I think, I'll let this thread die now.  Thanks @phil_t for helping me think about this from a different perspective.

Share this post


Link to post
Share on other sites

Which really only leaves me with questions regarding the Entity class itself.  At the very least I think all I need and id, a container for the components(for each id), an add function, and a remove function.  So I need:
to instantiate Entity in my main
use it to call _e.AddComponent(new component(position));
repeat for all component for each ID.  
use _e.Remove();  when something is deleted from the game world.  
Does this sound about right? It doesn't to me, because I'm not using to ID to assign any sequential ID's.  It seems like I want to use a dictionary<> to link the id "key" to the component list "value"?

 

 

You don't really need an Entity Class, additionally you don't need to save the Entity ID in your components. I will explain why further down.

 

 

In the EntityManager, he defines (in Java)
HashMap<Class, HashMap<Integer, ? extends Component>> componentStores;
 

 

 

I don't know the exact context, but i think you have to look at it like this:

The "Class" is the type of the component (e.g. "Position"), for each of your component type you have a HashMap with an entity ID (the integer) and the instance of the component.

 

So for each component exists a Map, that saves the all component instance with their IDs. You can then easily accessing every component via its type and the entity ID.

 

To come back to your problem with the Entity Class. You don't need one, an entity is just an ID like a key in a Database. Your componentsStore / EntityManager acts like a Database and its tables.

 

When adding a component to an entity, you just add an entry to the HashMap of that component type. Deleting an entity is just removing all components with that ID from all component HashMaps.

 

In your system you can get the HashMap of a certain component and iterate over it. If you then need some other component of that entity, you will have always the ID and can look it up via your componentStore.

 

Edit:

I don't know if C# has that concept of templates. If not it will be difficult to create something generic like those nested HasMaps.

The benefit over your 

Dictionary<uint, List<IBaseComponent>> componentStores;

is that you always know which component type you want. So the nested HashMap is very cache firendly since it will only contain components of the same type and you will iterate through them very often in your systems. Additionally you are not able to easily iterate through your Dictionary only wanting a certain component type. Moreover you need to search your nested List for the right component type. 

Edited by JulianLoehr

Share this post


Link to post
Share on other sites

After re-reading through a bunch of articles, I came across this again; which lead me to the source code on github.  Going through this again answers my questions from the OP on "What is the bare minimum required"?  However, there is a few things I need clarification understanding.

In the EntityManager, he defines (in Java)

HashMap<Class, HashMap<Integer, ? extends Component>> componentStores;

 

That's... not very nice, at least not in Java. Ashley (artemis inspired framework) did this, whereas artemis-odb and my own dustArtemis (both Artemis forks) ended up in plain arrays instead of int->component mappings. Turns out Ashley performance for iteration got quite a hit given that you'd make hash lookups for every system, for every entity they processed and for every component they needed. That's a lot of hash lookups.

 

Instead what you have is a map from component type to component container (you can do that with anything that represents your component types, class objects, strings, enums, plain ints, whatever). Then that component container is a plain array or list of components, and to get a component of an specific entity you'd do container.get(entityID). Thats no hashing or anything, just jump to an index into the array and fetch the component.

 

This has a downside, if your player entity has an ID of 200, and its the only user of Camera component, you will have an array there that can hold at least 201 components (0..200), 200 of them being 'null' (since entities from 0 to 199 don't have Camera). You waste memory but you you index directly into the array. If you use value types for your components, you'll waste a lot of memory, if you use references, you'll waste very little but you'll have an extra pointer indirection. In C#, int->component dictionary with value types might be worthwhile or might not,  use whatever is most convenient.

 

You're free to look into dustArtemis source if you want to, I trimmed various classes from original Artemis. The important stuff is in World, EntityManager, ComponentManager and EntitySystem classes. Component is just a tag interface that does nothing, entities are plain ints now. Don't even look at the "managers" or "systems" folder, that's just unimportant fluff.

 

EDIT: I made this post which is sort of an overview of an ECS without all the implementation details. Read SeanMiddleditch's post too. Don't pay attention to the rest.

Edited by TheChubu

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this