I had a talk in the office about what Entity Systems in game development are, how they work and how they can be applied. As there was quite some interessent in the topic I decided to write a post here, too. I first got in touch with Entity Systems during the researches while writing my master thesis titled „draft of a component based game engine for browsergames“ back in 2012 at Gameforge.
Basics of Entity Systems
Entity Systems are not bound to the rules of object-oriented development paradigm, which makes them appear kind of weird to developers in the first place. Understanding Entity Systems requires a paradigm shift. However the datamodel they are based on, is relational one. It doesn’t matter if you finally have to persist data to a database for an MMO or just use it for a singleplayer 2D-platformer game and only need the concept applied locally in-memory.
Extension vs. Composition
As motivation let’s think about a common issue in development caused by class extension.
Usually you build a class hierarchy to reuse code shared by different classes. On top you have some kind of GameObject which has limited common fields and methods carried by every entity in the game. All following classes are extended by it and add functionality or override default behavior from a parent class, depending on the level in the hierarchy where they are put.
Let me explain this with an example: Let’s say we have a Player character and a NPC in an open world RPG. Both have a lot of attributes and abilities in common. They have a place where they currently are in the game world, they can walk around and interact with other characters in multiple ways. Both are objects rendered by the game and both are physical objects underlying a physics system. The main difference between those two is, one is controlled by the player himself while the other is controlled by some AI. Pretty much simplified a class diagram could look like the following.
Seen from an oop perspective this approach absolutely makes sense, as it is a straight forward approach to reuse existing logic and add functionality as a kind of ability. A disadvantage of that approach is that you might get a pretty long and broad class tree, if you add more attributes, methods and systems. What if you must change order of the classes in the hierarchy? Think about what such a structure would look like in a database and how many joins you would need, if you build an MMOG. This additionally disregards the fact, that such a structure will kill every performance out of your game engine and therefore lead to desasterous scalability, if you rely on normalized tables. NoSQL databases can kick in at this issue but will require lots of calls, too, until one object is put together.
If you do have an exact plan from you Game Designer how the final game will be like, which he sent you right from his ivory tower, you can probably take this approach and finetune every bit of the enigne afterwards. But reality differs in this point. Game Deginers want to experiment whit concepts. Often a quick prototype is needed to evaluate an idea, or do some balancing to existing parameters. A good changability therefore is crucial. A good changability means faster answers to questions like „what if that specific stone from now on has magical abilities … at full-moon?“. What if you need to apply the same behaviour to an object on the other side of your class dependency tree later on? Probably for a horse at noon? Sounds ridicolous? Well, ask your game designer then. In such case functionallity is often put to a upper class to avoid code duplication. This however has the backdraft, that every single object derived from there on will share the new fields and methods. Sure, you must not use it, but nonetheless that would be complete nonsense.
To get to the point: Class inheritence leads to a long and broad class hierarchy, which gets more complex everytime you change or add something. Functionality needed in other classes will be put to upper classes. This will make the once thin classes fat, as every functionality needed in multiple classes will climb the class hierarchy up. This contradicts the separation of concerns principle. In the case of MMOGs bad scalability and performance will result, too.
So now what? Game over? Giving up? Sure not, we’ll never surrender! There is a different approach: Composition. Let’s get back to our example of an NPC and a Player-character. In the case of composition you would have two classes without any dependencies between them. Still they should share everything they have in common. The things in common are exactly what you put into components. Every data belonging to each other and necessary for calculations in the game are put into one component. Components are split up by „aspects“. In our example this would mean, Players and NPCs both have a Render-Components and a Physiscs-Component, while only the Player has a Input-Component which is replaced by a AI-Component for the NPC. They don’t extended some kind of common GameObject. Nor the Player, neither the NPC has components not needed. Look at the following example.
Another advantage of this design approach is, that you move away from the truely developer minted language and apply a more domain specific language to the code aswell. This improves communication between developers and other stakeholders involved in game development.
That approach allows you to reuse components, where it’s needed while game objects reside decoupled. A gain in flexibility is the result due to a higher changability. Now bring me back that only-at-full-moon-magical stone!
Elements of Entity-Systems
Entity-Systems consist of three elements.
An Entity is acutally not more than an globally (UU)ID. That’s it. No logic. No data. Only the ID. By adding components the entity in the game could be a player, a weapon, a dragon or a loaf of cheese. But: The entity itself doesn’t know what it is!
If you reassign all components of one entity to another one, you actually change what the entity is. Think about what that implies for a moment. You can transform a dragon to refrigerator by changing an ID! Now think of how you would build such a flexibility in clean oop with less code.
Components carry the data belonging to one aspect of a game object. They don’t carry any logic! Setters and Getters are the maximum methods they could have. However they are not required and I wouldn’t even recommend adding them. Why would you need them? Validation? Stop it! You’re thinking oop again. Unthink that instantly! Though you may generate them, changability increases with public fields. You will always add or remove fields to components – never functionality. You can think about a component as a database table, with an additional id-field.
Probably an example is useful here. The following diagrams shows some sample components which may apply to a unit in a 2D RTS: A 2DPositionComponent, a ProductionPriceComponent, a WeaponAttackComponent and an HealthComponent.
Do you already think that extending the 2DPositionComponent with an additional z-field would make-up a very good 3DPositionComponent? What have I told you about thinking oop? Stop it!
Building good components how ever is a science on its own. This topic is dicussed by Adam Martin in his post about what makes good components and good entities.
Components don’t necessarily carry data. They may be used as labels or markers, aswell. Thus they can declare a entity as Renderable or Movable. Components may be added or removed to an Entity at any time while systems will always work on their set of component types bound to their common aspect.
This finally is where the logic comes in. Usually games use a game loop where all logic is calculated in a endless loop called game loop. Ideally the code calculated here is seperated in Systems encapsulating different types of calculations following the seperation of concerns principle. So there is for example a PhysicsSystem calculating physics and a RenderingSystem used for rendering purposes. This separation is applied in Entity Systems, too. However Entity Systems follow an approach more likeley known from the functional programming paradigm.
Each system updates the values of one or more components per turn. For example a PhysicsSystem may influence the PositionComponent despite the actual inputs of the Player. Think of a Player falling off a cliff: The Player falls as Physics kicks in here. The same would happen to a stone for example.
All systems run after each other in a predefined order. The systems can be categorized in input, processing and output-systems. They should be processed in that order, too, as the values of components are influenced by the order systems change them.
- Input systems: Set all values carrying the inputs for processing (e.g. Movements, Actions by Players)
- Processing systems: The main processing systems depending on the inputs (e.g. Buying Items, Physics)
- Output systems: Systems used for Output (e.g. Rendering)
After every system has run, the game loop has made one turn and the next one starts. Want to build a round-based game? Sure! Simply make the „end my turn“ button cause one run of the game loop. Realtime calculations? Use an endless loop!
Now we come to a huge advantage of the systems. As they only sequentially update standardized data, the processing is extremely fast. No joins over lots of tables or class hierarchies! Entities are not used at all. They are not selected. Why should they? The stone does fall the same way off the cliff as a player does. They only differ in the parameters needed for the calculation of how fast they fall and when they arrive at the bottom. But the fact that calculations have to be done for that is independent from the entity itself.
As the systems should work independently anyway, they are good candidates for multithreading. Not every system must run on every cycle. Consider reducing calculation loads for entities not visible to anyone at a time. Did the NPC move if there was no one there to see it?
If not used in a classical gameloop the systems execution order must not even be anyway lineral or bound to anything. This decouples the systems even more while making them more changable and reduces side effects. However this means a lot of thinking about which data is actually needed at what time.
There are some Implementations of Entity Systems out for several languages. Most of them extend the basic principle explained here in some way. Implementations for C++, C#, Java, ObjC, Ruby and Python can be found in the Entity Systems Wiki. The Java based Artemis framework is available for C# and ObjC, too.
My experience with Entity Systems led me to some leasons learnt I can recap here.
Use Entity recycling
If you always create a new entity for any object, you will fill up your datamodel very fast. Entities often have a limited lifetime, until they get destroyed. As example think of bullets in an FPS. Lots of „dead“ entities will fill up your database and/or memory. Therefore you should implement some kind of entity recycling and reuse entities existing, but not used anymore. This will save both, memory and performance.
Don’t handle off-screen components
In the case of single player games, in which only a part of the game is visible to the player at once, you should not process all components all the time. Rather you should only process those, needed next and mark the others as inactive. Think of an 2D-platformer game in which the player may only run in one direction. It’s enough to update the components currently on screen plus, let’s say the following two screens. No one cares about the rest, as their update would not be seen by anyone. Doing so saves performance especially on mobile devices, for which many of those games are made nowadays.
One addition I made to my Entity System are Assemblages. They allow me to prebuild collections of components with given preset values for later instantion. Assemblages may also be considered as some kind of archetype. Lets’s say I have an Assemblage called Starship to instantiate a Battlecruiser which will be used in the later game. All Battlecruisers have the same components and starting values. The design may look like the following.
The main advantages of assemblages are, that later entities can be defined once at a single place and used often later on during runtime to be spawned into the world.
Handling Messaging and Metadata
You really should not send messages around an entity system. Rather use components for carrying data from one place to another.
The same applies to meta data. Just use (new) components for them. It will be easier to remove or change these if they are obsolete or have to be altered some time.
Databases are optimized for doing bulk operations. Thus use them for processing in the systems as much as possible for best performance.
Entity Systems solve quite some problems of game development – especially for MMOGs. Game data and game logic is seperated strictly from each other. Entities themselves are anonymous, as they don’t carry any data. Components encapsulate and group game data belonging to one aspect, but don’t carry any logic. Systems do the heavy lifting of data processing based on components (not on entities!) as batch processing, which is very fast. Therefore Systems use a processing model computers can handle very performantly.
It’s quite a paradigm change. But one, you won’t regret. You escape the dependency hell of broad and deep class hierarchies eventually destroying modifiability of a whole game. Systems split up the processing to specific smaller pieces following the separation of concerns principle.
Overall Entity Systems allow data oriented design in game development, which allows faster processing. See the talk about data-oriented design by Sean Middleditch from the DigiPen Game Engine Architecture Club.
I strongly recommend reading the posts of Adam Martin on Entity Systems in his blog, linked bellow. On any posts you should read the comments, too. Many misunderstandings are discussed there. Some posts contain code examples, too:
- Adam Martin: Entity Systems are the future of MMOG development – Part 1: Intro
- Adam Martin: Entity Systems are the future of MMOG development – Part 2: What is an entity system
- Adam Martin: Entity Systems are the future of MMOG development – Part 3: More in what is, and isn’t, an entity system
- Adam Martin: Entity Systems are the future of MMOG development – Part 4: Introduction to MMO Development Practices
- Adam Martin: Entity Systems are the future of MMOG development – Part 5: initialization, storage, and data
- Adam Martin: Entity System on Android phones – a concrete example using Java
- Mick West: Evolve Your Hierarchy
- Richard Lord: Finite State Machines with Ash entity system framework
- Scripting with Artemis Entity System Framework
- Entity/Component Game Design That Works: The Artemis Framework
- Sean Farrell: A Critique of the Entity Component Model