Composition over inheritance.
The basic idea that instead of having one specific class for each kind of entity in your game that is part of a long inheritance chain with "Entity" as the abstract base class, the class "Entity" doesn't do much more than handle a list of abstract components. Those components hold the data the entity needs to interact with different mechanics in your game.
So every entity in the game is of class Entity, but differs from other entities by its specific combination of components.
This allows you to mix and match components to create new entities. For example:
- Want a shelf to appear in the game? Create an entity with the "renderer" component that says what 3d model to use.
- You don't want the player to walk right through it? Add a "collider" component that says that this shelf is a solid box with a certain width, height and depth.
- Want it to also act as a container? Add the "container" component with a list of contents and a maximum capacity.
- Want the shelf to also be a secret door that can open and close? Add the "door" component to it that remembers whether the door is currently open or closed.
- Want the player to alternatively be able to smash it? Add the "destructible" component with an amount of hit points.
OK, so much for the data, but what about the code, you ask? Where does that go?
Well, there are two competing design philosophies here:
- Entity - Behavior. The components themselves implement the mechanics by implementing virtual methods like Initialize, Update, HandleEvent etc.. This is a bit closer to the object-oriented philosophies that any object should be a "smart" piece of data that governs its own behavior.
- Entity - Component - System. The components are just "dumb" data-holders that contain no or only minimal program logic. The actual code is in Systems. The systems each iterate over all entities that have certain combinations of components and implement the mechanics that use and manipulate that data. This approach seems a step back from the object-oriented design that was popular in the past two decades back to how games were designed in the age of C. But it recently became very popular again, because it makes it a lot easier to optimize for CPU cache usage and organize your logic in a way that makes it easy to parallelize on multiple CPU cores.