Overview
Thanksgiving is this week. Time to make pineapple glazed ham, pecan pie, sweet potatoes, and cranberry sauce. In the meantime, I'm working on developing a video game and I want to talk about Entity Component Systems (ECS). ECS is based on composition over inheritance, and storing data in Structure of Arrays over Array of Structures. Composition is easier to implement coherently, and a Structure of Arrays architecture keeps relevant data together so that it's faster to load into CPU cache.
I'm going to explain ECS in the context of game development. Entities are very simple, they are a simple integer-type identifier that represent any active "thing" that exists in the game. Components are a simple structure of relevant data. A system applies logic to components.
Entities
Your main character is represented by a unique entity. Every bullet fired has a unique entity. Every enemy has an entity. The entity acts like a pointer. The game engine can find all of the relevant components if it knows the entity value.
Components
Components are simple structures, usually literally a 'struct' in C++. A good example is a position component, which identifies a position in 3D space using X, Y, and Z axis coordinates that are floating point variables.
// Component example
struct position {
float x;
float y;
float z;
};
One entity may have many components. A character could have a position, velocity, health, inventory, etc. However, instead of storing all of that in a character class, which could be thousands of bytes in size distributed across the heap, the data is stored in components as a Structure of Arrays.
Array of Structures:Structure of Arrays:[ character1(\ ), character2( ), character3( ), ...]
[ , , , ... ] [ , , , ... ] [ , , , ... ] [ , , , ... ]
System
Each system iterates over components and updates them. For example, a gravity system might update a velocity component by applying downward acceleration every frame.
// System example
function gravity() {
for(auto& velocity : velocity_components){
velocity.z += -9.81 * Time.deltaTime;
}
};
The power of this design is that the gravity system can iterate over
array is much faster than reading the[ , , , ... ]
[ character1(\ ), character2( ), character3( ), ...]
array because data is loaded from memory in pages. If we fit more data into a single page, then we can process the entire array in fewer page loads.
Conclusion
Next time I'll talk more about how ECS enables composition to make development easier and faster.
Back to Home