1
\$\begingroup\$

I have read many articles about ECS patterns. Many of them are clear on what the entity and components are but don't really talk about the system because it "varies" or just use plain English to describe the behavior like "it finds the entities the system should work on", but how exactly that happens?

Let's say we have an Entity class which holds the all the components it needs (Transform, Texture, and Rigidbody). Now I have one system called RenderingSystem that uses Texture and Transform to render the entity to the scene. Then how would this RenderingSystem efficiently find all the Entities that need to be drawn on the scene?

\$\endgroup\$
3
  • \$\begingroup\$ Perhaps you want to implement a SceneGraph that will hold all the entities ? \$\endgroup\$ May 2, 2019 at 5:05
  • \$\begingroup\$ Maybe this can help approach to scene graph with entity/component systems? \$\endgroup\$ May 2, 2019 at 5:07
  • \$\begingroup\$ @ColdSteel if you mean a tree-like structure (parent-child), then I don't think you can leverage the advantages of ECS pattern, besides even you have a tree-like structure to hold all your entities to iterate through, what you would do to find the systems they need? Of course we can compare one by one like if the entity has Transform and Texture then use RenderingSystem, but I think it will increase the overhead too much \$\endgroup\$ May 2, 2019 at 5:30

2 Answers 2

2
\$\begingroup\$

There are a couple of ways, and they will depend on the implementation of the rest of your system. Here are a few of those I've seen.

You could manually tell the system(s) that a new component of a specific type has been added or removed to an entity. The system then goes visit the entity, and checks if there are other components that would make this entity interesting, in which case, it would add the entity to (or remove it from) its "list of entities to work on".

Another option is use events to achieve the same thing: when a component is added to an entity, an event that contains the id of the entity and the type of the component is raised. The systems interested in the component type listen to the event, and react to it in the same way as when done manually. This approach could be a bit easier to work with, as the developers focus on the system instead of the systems and components.

Another way I've seen is to store the components in arrays, each component type having its own array, and the index being the ID of the entity. This makes it so that the Entity and each component has the same identifier. When an 'update' has to be performed, the system just goes through the arrays of the components it's interested in, and if all the arrays have a component, it assumes that they belong to the same entity and act upon it. Implementing this requires another level of indirection between the id of the component and where it's actually stored to not waste too much space. (I believe it's something like that that is being done in EnTT.)

I've also seen theories about components stored in an SQL database. Each component type has its own table, and a SELECT fetches all the components that belong to the same entity. These seemed used on large games (MMOs).

Keep in mind that an ECS is a means to an end, not an end in itself. The advantages of an ECS over the 'traditional' hierarchy are efficiency and ease of use. If you decide to use an ECS to make your architecture easier to use and simpler to evolve, you can sacrifice a bit of the efficiency for the first couple of iterations of your architecture.

\$\endgroup\$
1
\$\begingroup\$

First of you should have a way to list all your entities. A simple list, a scene graph with only releveant entities or something completely different.

Now, one simple way to know if an entity got a certain component is to have a component flag for every entity. Whenever you create an entity or modify the components (only add and delete components from that entity), you set a flag.

For example, in c++ you could use a simple bitflag. IN this example you got 5 components, your components Transform, Texture, and Rigidbody could be the first, second and third component, Position fourth and Sounds the fifth.
So if you used a char as a bitflag and the char for entity X looked like this

//char flag  = "00000011"

Then your entity would have a Transfort and a Texture component.

The advantage of bitflags is, that you can easily check them and change them, as they are only binary operations.

char flagRenderingSystem = oxo3 // "00000011"
                                //char flagEntity "00001011"
if(flagEntity & flagRenderingSystem == flagRenderingSystem) ( 
   renderThisEntity(); //"00001011" & "00000011" = "00000011"
}

Best part of it, you can save this as a list of entitys that needs to get rendered. Only if an Entity changes, its flag has to be reevaluated.

\$\endgroup\$

You must log in to answer this question.

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