top of page
Search
chilaganirajesh95

ECS Update #2

In my previous blog, we learned various ways to implement an ECS system and the design choices that I took for my ECS system and the reasons for those choices. In this blog, we will discuss the updates and new interfaces I added to my ECS system.


Updates & New Interfaces

From my previous blog, we know that I have a class which is a storage pool for each type of the component (ComponentStorage). This class stores all the instances of a component type.

Ex: To create a pool for TagComponent you do it as below

ComponentStorage<TagComponent> NewPool;

I also have a class which is a container for all pools(Registry). This class contains all pools so Registry is where you can get all the data.

One challenge I was having with this design is I have components and pools but how do I associate a component data to an Entity. How do I know which instance of a component in a pool belongs to which Entity?

First I have to figure out what is an Entity in my system. An Entity is just an identifier so at its core it is just a number and it should be unique. So I need some kind of a unique Id generation for my Entity. I added a simple function GetUEntityID() that generates a Unique Id using the time. I am using the std::chrono library for time-related functions.


So I got my EntityId which is a unique Id generated based on time. So how do I use this EntityId to associate the components? One way you could do it is to track the index of components. You can map the index of the component in the pool to your EntityId and use it to reference the component, this is the method I used initially but there is a problem, whenever a component is removed you have to update all the remaining indices mapped to your entities which might not be an ideal thing. The other way is instead of mapping the index of a component map the component itself so that it will be easy when removing components and no additional operations are required.


Now we can create an EntityId, add components to it, get those components, remove them, and can perform operations on components using the Registry. At this point, we can use the ECS system in a project and work.

To make the ECS system, even more, simpler to use I have added few more interfaces. I have added a ComponentStorageIterator class which allows you to iterate over all the components in the pool. In my previous blog, I mentioned one of the advantages of using pools is we can iterate over a certain pool and perform an operation for example If I need to update all the physics data I can do it if I have a pool.

The ComponentStorageIterator class provides the interface so that it is easy to iterate over a pool and it is very similar to a map iterator in usage. In fact, it is just an abstraction of the underlying map iterator. All you have to do is ask the Registry to provide the iterator by specifying the component as a template parameter.

In the above example, I am iterating over a pool of RigidBodyComponent which is a struct that I created. So you use GetComponentStorageIterator method to get the iterator by providing the component as a template parameter. If no such pool exists the Registry returns an empty iterator. I have overloaded basic operators like an arrow, increment, decrement & other operators. You have to use -> to access the internal members just like a map. So you have first & second that you can access from the iterator it->first is always the corresponding EntityId and it->second is the component itself. The iterator makes it very easy to iterate over a pool and perform operations on all the components in a pool.


I have also added a new Entity class which is basically an abstraction for the EntityId. Though entity is just an Id I think everyone prefers using it as some kind of a container for all the components it can have. I think the reason for it is because it is easily readable/understandable when you write Entity->AddComponent<Tag>() rather than using some Registry function which adds a component by taking EntityId and the component as parameters. So I added an Entity class with EntityId as the member so we can use the Entity class to add, remove & get components.


I have added components for rendering & rigid body data and updated my game to use the ECS for submitting meshes and for updating the movement.


Next Steps

Next, I will be working on the human-readable and binary files for the Entity & components. It is challenging to come up with a generalized approach for creating binary files for the components as a definition of a component is up to the user and it is not possible to know what the human-readable information of a component represents. I will probably have some constraints when creating a binary file.

10 views0 comments

Recent Posts

See All

Comments


Post: Blog2_Post
bottom of page