Hey guys, I've been doing a lot of reading on Entity Component Systems and I figured I'd give it a go. I have a basic design layout and I was hoping to get some feedback, both to help out a beginer with this new design implementation and to so I can see people's thought processes.
Here's what I've come up with (sorry, no code right now):
Entities:
- Just a Universally Unique ID (UUID).
- Since an entity is a UUID, this will be implemented within an entity manager (see below).
Entity Manager:
- Manages entity creation and removal.
- Entities are stored in an array (maybe, this seems redunant as the UUID will act the array index but I will need someway to store created entities, right?).
- Each entity has it's own creation method where an entity is created and components are created and assigned to the newly created enity. This is so it's a simple function call to create as many tanks, jets, unicorns, sharks with freaking lazer beams, etc as desired.
- This means the entity manager will be keeping track of components and whom they belong to. To keep it fast and simple, I figure an array for each component where the entity's UUID can index into said array(s) to get it's components. This way systems can simply iterate over the array(s) it needs and to make use of pre-fetching and caches.
- Entity removal will cause the UUID to be thrown into a list of some sort so that it can be recycled (on entity creation). This will prevent the UUID from becoming impossibly large should a large number of entities be created then destroyed.
Components:
- Data only.
- A list of components is held by the entity manager (see above).
Systems:
- One system per aspect (physics, AI, etc). These are independed of each other so it should be trival to put them in different threads if desired.
System manager:
- Primary use is to be a black box to hide the data structure containing the systems (array, vector, linked list, who knows).
- This will also make it easy to have each system in a thread (if desired), in the add method just start a thread for the system, or add it to a data structure that is iterated over every frame, or whatever).
- To keep it simple and easy for now, it'll be a vector.
- This can also provide a way to prioritize systems, pause systems or outright remove them (though I'm thinking this is probably a stupid idea; I can't really think when I'd want to remove a system outright or even to just pause it).
- I'm not even sure If need this. It's a 'nice-to-have' in that it helps seperate world functionality (see below) from system specific functionality. But this could be my OOP background nagging me.
World:
- There's only one world so this will be an object (as in OOP).
- Will contain an entity manager and system manager.
- Will have methods to load & save the world.
- Will contain the main loop.
- Will behave as everyone elses world object (I'm sure).
I think this is a pretty decent design (to start with) but I'm curious as to what you guys think. After all I could be heading toward a world of hurt and not realize it or be on my way.
I do have one question though. My entity manager contains the list of components used by the entities. This is because I would like to go EntityManager.tank(...), EntityManager.SharkWithFreakingLaserBeams(...), etc rather than manually type: create entity; create componenets; assign components to entity; each time I want to create something (the only difference is what components are created because it depends on the entity, so why not automate it?). However, this leaves me in a bit of a pickle for systems. Since they are two are seperated objects, the system manager does not have access to the list of componenets that it needs to iterate over and do its thing.
What would be considered the best idea to solve this (yes, I know there's a hundred different ways I can solve it). I'm thinking of something like:
- The entity manager has a 'get components' function(s).
- The components are fed into the system manager's update function.
- Each system takes the components it needs to work on and iterates though them, doing it's thing.
That's probably the easiest solution I have, for the design I have; but I don't think it's upgradable. IE: What if I want to change the system manager from a data structure to a thread creation implementation. Ideally I can simply make the change in the add/remove methods of the system manager, but now the solution to give the system manager the list of components goes out the window since the system manager no longer has an update function (each system is in it's own thread so it'll be best to let it deteremine when it needs to update since some systems will be likely to run at different times. EG: render all the time, update at the frame rate).