header image
 

Entity systems, input and persistence

As my development of Heimdall continues, I run into various problems and difficulties. It’s expected, a project of such complexity can’t be all smooth sailing. Right now I’m implementing the core logic of a game server, a foundation for the whole game world simulation and processing. As mentioned before I’m using an entity system approach. So what exactly is an Entity System?

In a nutshell, an Entity System is a way to organize game entities. By ‘game entity’ I mean every object that exists in the game world. So it includes players, items, enemies, interactive terrain features, invisible script triggers etc. The traditional way to structure game entities is an object-oriented class hierarchy. There is some base “Game object” class, then more detailed “Movable object” or “Trigger” classes and so on. It’s pretty self-explanatory, widely used and everyone understands it. So why not use it? Well, there are some problems with hardcoded deep inheritance chains. First, you need to plan pretty much everything right at the beginning of the design process. Once you have a class hierarchy, it’s very hard to change it afterwards. Even worse, game entities are hard to partition into perfect tree. Suppose we have a Human class and a Vehicle class. They both derive from a Mobile class. But what if we want some objects to have an AI and not be controlled by player(s)? We need to either introduce another base class(es) – Controllable/Scriptable, or cram input handling and AI into each class, even if that code won’t be used at all half the time. First solution introduces multiple inheritance into our class tree, and that is A Bad Thing most of the time – the code will be even harder to maintain and changes to the class structure will be almost impossible. The second solution bloats classes with unnecessary code that is only needed for some objects. As more such situations appear, base classes will contain more and more functionality, leading to feature overload and unneeded complexity.

What can we do about that? Entity System or component approach tells us to separate related object data into components, and to partition functionality into systems that acts on said components. There will be no traditional class hierarchy, just a basic Entity class that only really has a unique ID and is an aggregation of data components. Components are just bags of data, they contain no logic themselves. Systems are where the logic lies – they process components, may communicate with each other and generally make the game run. It’s worth saying that systems should be indiscriminate: each and every entity should be “equal” for them. In practice that means systems shouldn’t feature code like this:

if (entity.HasComponent(SomeComponentType))
   DoSomething();

Systems usually “subscribe” to components they are interested in. Let’s say we have a Rendering system. It may be interested in Position and GraphicsModel components. Then usually every game tick entities are dispatched to systems depending on such “subscriptions”. Rendering system draws entities it’s been given using just the data it needs. AI system acts on all entities that have AIState component. This way both data and logic are nicely separated and partitioned into manageable chunks. All entities have only components they need. We can have a player-controlled human (has InputState component), or AI-controlled human (has AIState component). No multiple inheritance needed and we have great flexibility. We can mix and match, create entities from templates containing lists of components, even make templates that include each other to facilitate data reuse. Such flexibility and data-driven design is a great asset for any MMORPG.

So we have an Entity System and all is great. There are still practical obstacles and implementation details to overcome. If we design a MMO game server, we need data persistence. Every game entity needs to be stored in some way, usually in a database. I’m using mongoDB – an open-source, NoSQL, high-performance document-oriented database. I feel it’s better suited for the job than traditional relational databases, game objects don’t map well into SQL tables and rows. mongoDB is also damn fast, just look at their production deployment list. I’ve done some tests myself and the accounting system already uses it without issues.

How do we store game entities then? Because entity is just a bag of components and components are just bags of data, this should be relatively simple. We just need to ensure that all Component implementations have proper DB (de)serializers. We also need some form of creation engine that will construct entities from templates, because manually adding each component every time is tedious and prone to errors. That implies having template storage, designing template format and parser for it. My Entity System implementation is based on Artemis – a C# port of a Java ES under the same name. I’m modifying it as I go since it’s got some rough edges. It doesn’t have any support for templates and modifications to the entity factory are required if I want proper integration with persistent DB (generating unique IDs is an issue there).

Another problem lies in the implementation of the input system and I’m not sure how to solve it yet. We have a game server. Clients connect to it and send network packets with input commands. Now we need to pass that input data to appropriate system(s) that can in turn act on Player Character (and possibly other) entities. How to do that without breaking encapsulation? Networking layer shouldn’t manipulate entities by itself obviously. Each client connection has a player ID assigned, which is basically the player character’s entity ID – that’s determined upon login. Data in each incoming packet needs to be validated. This should be done by appropriate systems: if we get a “move character request”, network handler should pass the data to Movement system… But systems themselves should be stateless! Do we make an exception for input data? Or do we create a “MovementQueue” component that holds the input data and is processed and validated by Movement system? MovementQueue concept is nice because it can also be used by AI systems. Right now I’m in favor of the queue, but I’m not sure how well it will scale. What with other input data? Do we have an attack queue, speech queue etc? I can see a large number of “action” queues in the future if I do it this way. Or maybe we can make just one ActionQueue? But data required for different actions has different structure. Maybe there should be an “ActionDispatcher” system? Questions, questions!

~ by omeg on January 30, 2012.

code, entity systems, game development, Heimdall

2 Responses to “Entity systems, input and persistence”

  1. This entity system seems like an attempt to turn C# into a functional language. Perhaps F# would be a better choice, if you are embracing this style anyway? 🙂

    As to input system, why not treat these “input packets” as entities themselves and for example make the MoveCharacter() function take two params: the character and the movement?

  2. Entity systems design is independent of language, in fact most implementations I’ve seen were in C++. Also C# already supports many functional constructs, like closures and lambda expressions. 🙂 It’s mostly about flexibility and data-driven architecture, not the language itself.
    Interesting idea with the input packets. I thought that only game world objects would be represented as entities, but that’s certainly not the only way to go about things. I’ll experiment and see what I can come up with.

Leave a Reply