Entity Component Systems

Entity Systems are the future of MMOG development – Part 1

A few years ago, entity systems (or component systems) were a hot topic. In particular, Scott Bilas gave a great GDC talk (http://scottbilas.com/files/2002/gdc_san_jose/game_objects_slides.pdf – updated link thanks to @junkdogAP) on using them in the development of Dungeon Siege. The main advantages to entity systems were:

  • No programmer required for designers to modify game logic
  • Circumvents the “impossible” problem of hard-coding all entity relationships at start of project
  • Allows for easy implementation of game-design ideas that cross-cut traditional OOP objects
  • Much faster compile/test/debug cycles
  • Much more agile way to develop code

I first started using entity systems in anger back in 2001-2003, when I was working on MMOG server middleware. We were targetting the few most painful problems in MMOG development, one of which was the difficulty of constantly changing your game logic after launch, which led us to entity systems. I learnt then that entity systems were an almost perfect solution to massively speeding up the development time for most MMOG’s, and for also allowing almost unrestrained re-writing of fundamental game features post-launch with very little effort.

That last issue is critical to the success of an MMOG: once an MMOG is launched successfully, its long term success or failure depends more upon the ability of the dev team to evolve that game into a better game month after month than upon anything else.

I learned a lot from that first run-in with them, more about the things that go wrong and what makes developing with entity systems particularly hard than about the things that went right. We also discovered that performance could easily become a major issue – although they are very flexible and dynamic, the lack of pre-compiled lookups and optimizations can make runtime performance disappointingly (unacceptably) poor. Why? Mainly because of the amount of indirection and checks needed to run even a single method call (but I’ll go into detail on that problem, and how to fix it, a bit later).

I moved on, and didn’t think about them again, until last year. In 2006 I joined the Operation Flashpoint 2 team as the lead network programmer, where we trying to make an MMO-FPS on an unprecedented scale, and I discovered that the programming team was considering an entity-system to drive the whole game. The attractions for the OFP2 team were different – mainly around the improvements to memory management they could get from it, and the stream-oriented coding (which is essential for PS3 development) – but it turned out to be something of a silver bullet for the “MM” and “O” parts of the MMOFPS. As the network programmer, discovering that an entity system was going to be the interconnect for all other subsystems was a huge relief: the entity system meant I could implement the complex latency hiding and prediction techniques with minimal interference with the coding of all the rest of the game systems. When you’ve got 20+ programmers on a team, you really don’t want to be placing yourself in a position where you’re going to have to redesign code for all of them just to make it “network friendly”.

whilst I was working on OFP2, I got in touch with Scott, and exchanged ideas on what the future might hold for entity systems, including additional uses for them, and on how to share this knowledge more widely. He encouraged me to start a blog (and, actually, a year later that was one of the main reasons I even started this blog, T=Machine), so I figured now was a good time to start (finally) writing about those entities :).

And to blame Scott for the existence of this blog…

Since then, I’ve been thinking a lot off and on about entity systems and their appropriateness for use in MMOG development (again!). Only this time around – thanks to OFP2 and some of the issues it threw up – I had a much better idea how to use them to increase performance rather than reduce it, and had come across some other major problems that they conveniently solve. Most obviously, they work wonders for PS3 development. Knowing how PS3’s fundamental architecture works, I can’t immediately see how you’d want to use anything other than a full entity system for game development. There’s so much horsepower in that beast that you can certainly write games many different ways, but it’s particularly well-suited to this approach.

As it stands, I’m beginning to think that next-generation MMOG’s are going to be practically impossible to develop unless based heavily around a core entity-system. “practically” being the key word – unless you’re willing to spend $100 million for your development…

“Anything is possible”, of course, so there’ll be many exceptions to that – but I think any team that doesn’t go this route is going to suffer a lot because of it.

I think most people would agree. But … recent discussions on game-industry mailing lists – and the experiences I had within games companies with programmers who were much better at programming than I was – made me realise that there’s a lot of ignorance over these systems, and many people aren’t getting anywhere near the full potential of them. So, if you’re interested, read on…

I’ll do this in a series of posts (it’s going to take some time to write it all up!), but it’ll go something approximately like this:

ADDENDUM:

EDIT, December 2007 – You may also want to take a look at Mick West’s introduction to entity systems for game development, it’s a shorter read than my posts, but narrower in scope.

NB: as I post the other parts, I’ll update the list above to link to them.

Entity Systems are the future of MMOG development – Part 2

Part 2 – What is an Entity System?

(Part 1 is here)

Sadly, there’s some disagreement about what exactly an Entity System (ES) is. For some people, it’s the same as a Component System (CS) and even Component-Oriented Programming (COP). For others, it means something substantially different. To keep things clear, I’m only going to talk about Entity Systems, which IMHO are a particular subset of COP. Personally, I think Component System is probably a more accurate name given the term COP, but then COP is improperly named and is so confusing that I find if you call these things Component Systems they miss the point entirely. The best would be Aspect Systems, but then AOP has already taken ownership of the Aspect word.

An entity system is simply a part of your program that uses a particular way of breaking up the logic and variables of your program into source code.

For the most part, it does this using the Component Oriented Programming paradigm instead of the OOP paradigm – but there’s subtleties that we’ll go into later.

We refer to an entity “system” instead of entity “programming” because ES’s are usually found embedded in a larger, OOP, program. They are used to solve a subset of problems that OOP is poor at dealing with.

So, it is generally a replacement for Object Oriented Programming. The two are mutually exclusive: you have to choose one or the other (although any complex program may have multiple levels of abstraction, and you could mix and match OOP and COP/ES at different layers, any given layer is going to be one or the other (or, of course, any other alternative way of structuring your program).

Common misconception #1 – Entity Systems are part of OOP
Common misconception #2 – Entity == Class, Component == Object

Where OOP has Classes and Objects, an ES has Entities and Components – but it is very important to note that an Entity is NOT equivalent to a class, and a Component is NOT equivalent to an Object, although superficially they seem to share some characteristics. If you think of Entities/Component’s in OOP terms, you will never understand the ES, and you will screw up any attempt to program with it.

The whole point of ES’s using a different programming *paradigm* is that this means there CAN NEVER BE a direct equivalent between Classes and anything, or between Objects and anything – if there were, it would actually be the same paradigm, and just be a variant of OOP. It’s not. It’s fundamentally different and incompatible.

What’s an Entity?

An Entity System is so named because Entities are the fundamental conceptual building block of your system, with each entity representing a different concrete in-game object. For every discernible “thing” in your game-world, you have one Entity. Entities have no data and no methods.

In terms of number of instances at runtime, they are like Objects from OOP (if you have 100 identical tanks, you have 100 Entities, not 1).

However, in terms of behaviour, they are like classes (Entities indirectly define all the behaviour of the in-game object – we’ll see how in a second).

So, entities on their own are pretty much entirely useless – they are coarse-grained, and they serve to do little more than to tag every coarse gameobject as a separate item. This is where Components come in.

What’s a Component?

Every in-game item has multiple facets, or aspects, that explain what it is and how it interacts with the world. A bicycle, for instance, is:

  • Made of metal
  • Can be used by a human
  • A means of transportation
  • Something that can be bought and sold
  • A popular birthday present
  • Man-made

At this point, please note: OOP does not have this concept of multiple aspects; it hard-codes all the aspects into one glob, and declares that the set of behaviours and values of data to be the single-aspected Class of an Object. C++’s Multiple inheritance and Java’s Interfaces can get you a small part of the way towards the aspects of an ES, but they quickly collapse under the strain in fundamental ways that cannot be fixed within OOP.

The way that an Entity for an item represents the different aspects of the item is to have one Component for each aspect. The Component does one really important thing:

  • Labels the Entity as possessing this particular aspect

It may do several other things, depending upon your implementation and the design of your ES. However, with an ES, this is the most important, because this is the basis of all method execution and processing.

What’s a System? (or subsystem)

An ES goes further than OOP in how it splits up the universe of code and data. In OOP, you make everything into Objects. With an ES, you have two different things that you split code and data into: the first is “Entity + Components”, and the second is “Systems”.

This is the source of a lot of the value of an ES. OOP is very good at implementing the part of any program that has lots of data floating around and lots of methods floating around which need to be executed only on a small, instanced, subset of the data in the program. OOP is very poor at implementing the “global” parts of a program, which have to operate “on everything”, or have to be invoked “from everywhere”. An Es solves this by explicitly dealing with all the global stuff using Systems, which are outside the realm of Entity/Component.

Each System runs continuously (as though each System had it’s own private thread) and performs global actions on every Entity that possesses a Component of the same aspect as that System.

There is a one to one relationship between Systems and AVAILABLE aspects (i.e. types of Component). A System essentially provides the method-implementation for Components of a given aspect, but it does it back-to-front compared to OOP. OOP style would be for each Component to have zero or more methods, that some external thing has to invoke at some point. ES style is for each Component to have no methods but instead for the continuously running system to run it’s own internal methods against different Components one at a time.

Typical Systems in a game would be: Rendering System, Animation System, Input System, etc.

The Rendering system wakes up every 16 milliseconds, renders every Entity that has the Renderable Component, and then goes back to sleep.

The Animation system constantly looks out for anything that would trigger a new animation, or cause an existing animation to change (e.g. player changes direction mid-step), and updates the data of each affected Entity (of course, only those that actually have the Animatable Component, i.e. are animations).

The Input system polls the gamepad, mouse, etc, and changes the state of whichever Entities with the Inputable Component are currently marked as being controlled by the player.

In tradtional OOP, if you have 100 units on a battlefield, and each is represented by an object, then you theoretically have 100 copies of each method that can be invoked on a unit. In practice, most OOP languages use runtime and compiler optimizations to share those methods behind the scenes and avoid wasting memory – although scripting languages for instance often don’t do any sharing, allowing all the methods to be independently changed on each and every instance.

By contrast, in an ES, if you have 100 units on a battlefield, each represented by an Entity, then you have zero copies of each method that can be invoked on a unit – because Entities do not contain methods. Nor do Components contain methods. Instead, you have an external system for each aspect, and that external system contains all the methods that can be invoked on any Entity that possess the Component that marks it as being compatible with this system.

That’s not an Entity System!

Well … at least, that’s what *most* people I’ve worked with consider to be an Entity System. But even within a single project, I’ve found multiple different ideas of what an ES is, some of which are compatible, others of which are incompatible. Here are some of the other ideas I’ve come across that people thought were ES’s.

Alternative definitions of entity systems:

1. An ES provides a different model of class-inheritance to OOP, especially w.r.t inheritance of fields. For any given entity-class you declare which aspects that class possesses, and the actual class is looked-up at runtime by piecing together all the different aspects.

2. The same as 1., but taken literally for methods as well as fields, i.e. this provides an interesting way to mix-n-match inheritance of functions/methods. So long as methods are attached to the fields upon which they operate, and/or a “pre-requisite” system is implemented such that “having aspect X automatically causes you to also have aspect Y”, then this works quite smoothly. NB: this is implementing “modular objects”: the “aspects” are complete objects from the standard theory of OOP.

3. A variant on 1. or 2. where the aspect data is pre-compiled into a large number of OOP classes at compile time, so that at runtime you are just running “normal” classes, without any lookup cost of the dynamic “I’ve got an entity E which claims to have aspect X; just hold on a sec while I build a function table to find out what the heck to do now someone just tried to invoke function Z…”

4. A way of compiling standard OOP classes into runtime-data (note: disassociating them from their OOP-ness) specifically so that you can treat them as streamed data instead of chunked binary + data. The main value of this is to play nicely with hardware that has tiny tiny amounts of memory available in the code cache and/or very very slow access to fetch extra code, but has vast bandwidth to stream SEQUENTIAL data through the CPU. PlayStation consoles especially like this approach, as opposed to the typical PC approaches. Note that in this case, the idea is that the game-programmers and game-designers are UNAWARE that there’s an entity system – it’s a runtime/compile time performance optimization, not a design-feature.

5. A system design that revolves around excessive use of the Observer pattern, but does so using standard OOP techniques. I mention this because it’s a common (ab)use of the concepts of ES’s, but lacks much of the advantages. For what it’s worth … that’s the situation I was in when I first discovered ES’s. So, personally, I really don’t count these as ES’s. These are not an ES, but an: “OMG, I need an ES!”, but many people persist in thinking (and claiming) they’re a true ES.

NB: IMHO this is one of those “you really shouldn’t do this” classes of Entity System usage. Why? Because you end up just creating MASSIVE OOP classes with tonnes of independent implemented Observer methods tacked onto them. That’s fine as a general approach, it buys you something whilst remaining ENTIRELY OOP, but it also loses most of what ES’s have to offer, especially in the realm of flexibility and compound inheritance.

Who cares about ES’s and why? (where did they invent these from?)

1. Coders who are used to writing a graphics/rendering engine and trying to keep it isolated / separate from the rest of the computer game. They learnt that they can write the entire graphics engine using only PARTIAL information (a couple of aspects – no more than 2 or 3) of every OOP object that exists in the game-universe. They need to use: Renderable (do I have to paint it to the screen every frame? [it will have all the methods necessary to do that painting generically]), Updateable (does it potentially change in response to one or more game-loop-ticks? [animations are a great example of this – their internal state changes independently of how many times they’re rendered]),

2. Multi-threaded coders who are looking at the concept of aspects per se (i.e. Renderable as opposed to Updateable) to allow for coarse-grained multi-threading: you are allowed one thread per aspect, and this is guaranteed safe simply because the aspects are – by definition! – independent from one another. Since a typical ES will have a dozen or more aspects, you’ve just bought yourself reasonably effective performance scaling of up to 12 separate CPU cores, for free.

Also … going to the next level of difficulty and performance improvement, they’re looking for the largest possible individual (literally: things that “cannot be divided”) things that can be made the atomic level of multi-threading. The default position is that only manually-hard-coded atomic operations count, and OOP objects certainly are full of all sorts of multi-threading individual pieces so are far too coarse, but maybe components within entities are small enough to be the unit of atomicity.

3. Game designers who want to enable “everything to become anything”.

Do Cameras shoot people?

Do Bullets accept input from the player?

No?

Well … have you played Unreal Tournament? If you have but didn’t answer yes to the earlier questions then you need to find someone to show you a Redeemer being used in Alternate Fire mode (hint: you get to manually “fly by wire” the rocket from a first-person view inside the warhead itself).

ES’s allow everything and anything to be used as anything and everything, interchangeably, with no re-coding. That’s the beauty for designers – all the artifical constraints on design that were previously enforced by coders having to, you know, place SOME constraints just to write their own damn code and have it be reasonably performant and bug-free are suddenly lifted.

It’s true – you really CAN have strongly-typed safe code and yet have total freedom to pass any object to any method; at least, you can with Entity Systems.

4. Coders who go a bit overboard with the Observer pattern.

If you’re unsure about this one, and have used Observers a lot, ask yourself this: have you ever had that problem with Observers where you found that “just one base class isn’t enough”? i.e. one base class that implemented a handful of different Observers worked great, but as your system / game / application expanded you found you needed more variety in that base class, you needed multiple different versions, and you needed *every possible combination* of those different versions, because base-classes cannot/will not “stack” nicely on top of each other.

Thought for the day

Programming *well* with Entity Systems is very close to programming with a Relational Database. It would not be unreasonable to call ES’s a form of “Relation Oriented Programming”.

This needs a followup post, but you might want to think about that 🙂 both in terms of how the above statement could be true (hint: think about what most of the code you write for each System is going to look like, and what exactly it is doing), and also in terms of what the knock-on effects of this are if it is true.

Bear in mind that no-one’s yet managed to do OOP fast with Relations; the excessively high conversion cost between RDBMS and OOP – both at coding-time and at runtime – is still one of the biggest single development problems with writing an MMO.

Entity Systems are the future of MMOG development – part 3

Also known as: Nobody expects the Spanish Inquisition!

(because I’m now deviating from the original schedule I outlined in Part 1; what the heck, it was only a rough agenda anyway…)

Questions, questions…

First of all, there’s a bunch of good questions that have been raised in response to the first two posts:

  • what data and methods are stored in the OOP implementation of an entity?
  • where does the data “live”?
  • how do you do object initialization?
  • what does the ES bring that cannot be accomplished with an AOP framework?
  • what’s the link between entity systems and SQL/Relational Databases? (OK, so that one’s my own question from last time)
  • what, exactly, is an entity?

Let’s start with that last one first.

What, exactly, is an entity?

Obviously, I’ve already covered this from the conceptual perspective in the last post, where I defined them as:

For every discernible thing in your game-world, you have one Entity. Entities have no data and no methods

Great. But a couple of people were wondering what ACTUALLY is it, when you start implementing the thing? Is it a class? Is it an array of data? Is it a list of Components?

The last statement is particularly important: actually, entities have NO data and NO methods – an entity is not a stub for a class, it is not a struct of data, and – ideally – it’s not a list of Components. An entity is really just a name. Last post I also wrote that entities “do little more than to tag every gameobject as a separate item” – and that’s the key thing here, an entity is just a unique label for an in-game object.

I was a bit non-specific, because I didn’t want to say empirically that an entity cannot or should not be a list of components – sure, you CAN implement it that way – because many people do implement entities like that, and who’s to say what’s right or wrong here?

Although…I actually think that *is* the wrong way, and think that by the time you get to the last of these Entity Systems posts, you’ll probably agree with me ;). The problem is, the right way is usually too slow, so you’ll probably end up *to some extent* implementing entities as lists anyway, but if you do so as a performance optimization (e.g. by hiding that detail from the rest of the system) rather than as a logical implementation, it’ll cause fewer problems with your code in the long term.

So, to answer the question directly:

What is an entity?

An Entity is a number (a globally unique number)

Remembering, of course, that a String – or any other kind of unique label – is merely a fancy kind of number, not just in terms of how computers implement them, but in terms of how Mathematicians think of them. People tend to think that strings have extra features, for instance you can encode trees within strings easily (“root.node1.leaf”, for instance – as used in most OOP languages derived from C to navigate the namespace of classes, methods, etc) – although of course you can encode things like that in numbers, too, for instance “123045607” (using 0 to stand for the dot… i.e. “123.456.7”). But … you *really* don’t want to do this!

Gotcha number 1: only OOP programmers want to give entities hierarchical names. It can tunr out a pretty dumb idea, if you think about it: it’s usually an implicit refusal to let go of those OOP ways we’re so used to thinking in, when those OOP ways are exactly what caused most of the problems we’re trying to fix by using ES’s.

So, don’t be tempted into hierarchical encoding, and definitely don’t do ANY encoding in the entity names – there’s a much BETTER place to do metadata for entities (trust me).

And I’ll be calling the implementation of an entity a GUID from now on (“Globally Unique IDentifier”).

What data and methods are stored in the OOP implementation of an entity?

The answer for the previous question makes this one easy to answer: none. The entity is merely a label, and whilst you DO want to store and manipulate some metadata around that label (e.g. it’s kind of handy to have a list of all the entity names you’ve currently got in memory, and be able to rename them without breaking everything), you should be thinking of them as nothing more or less than a GUID (String. Number. Whatever!).

Where does the data “live”?

The first time I made an ES, I implemented the individual Entities as classes, and although I didn’t put any methods in those classes (that would just be bog-standard OOP!), I did put the data into them. It didn’t occur to me that I’d need to worry about where the data was living, so I just stuck it somewhere natural – in the Entity.

Of course, I’d made a cardinal error, because whatever feels “natural” to an OOP programmer is usually “completely wrong” in ES programming.

Anyway, the last time I did an ES I was a lot wiser, and so we put the data inside the Components. All of it.

Gotcha 2: ALL the data goes into the Components. ALL of it. Think you can take some “really common” data, e.g. the x/y/z co-ords of the in-game object, and put it into the Entity itself? Nope. Don’t go there. As soon as you start migrating data into the Entity, you’ve lost. BY DEFINITION the only valid place for the data is inside the Component

How does that work?

Well, you need to start thinking about your Components a bit more carefully here. I previously said that:

A Component labels the Entity as possessing this particular aspect

So, again, a Component is merely another “label”, just like the Entity itself. Right? Wrong. This is my fault – in the last post, I was trying to Keep It Simple for you, and glossed over quite a few things; because the very first ES I made, I treated the components as mere labels, that description came out most easily as “the simple version” of what they are. In more detail:

A Component is the chunk of stuff that provides a particular aspect to any Entity

…where “provides” means “does all the things that are necesssary to make this work”. Which means that all your Components certainly *could* be implemented as standard OOP objects. To define an Entity, you just provide a name (GUID) and a list of Component classes that it needs, and to instantiate that Entity, you just instantiate one object from each class (and then you need to somehow attach those in-memory objects to your GUID, probably by implementing the Entity as an empty class that just contains a GUID and a list-of-component-instances (which I said to avoid, but we’ll come back to that later)).

But, as you may have noticed by now, I’m vigourously against using OOP anywhere inside an ES implementation. This isn’t some strange dislike of OOP itself, it’s just that in my experience with ES development it’s all too easy for experienced OOP programmers to keep trying to sneak some OOP back in where it’s inappropriate, and it’s all too easy to delude yourself into thinking this is a Good Idea. And, worse, from the teams I’ve worked on in the past, it has consistently seemed that the better you are at OOP programming, the harder this is to resist…

You COULD implement your Components as OOP objects. But, really, if you go back to the definition of a “System” from the last post, you’ll see that the methods for acting upon Components should all live inside the Systems, not the Components. In fact, re-reading that last post, I notice that I explicitly described Systems as doing exactly this: “a System essentially provides the method-implementation for Components”.

One tiny exception to this rule: getters and setters are really useful. If you’re implementing your ES within an OOP language, you might allow yourself to implement Components as objects just to get the benefits of get/set and e.g. multiple different versions of each get/set that do basic type conversion, or integrity checking on data, etc. Be warned, though, that if you do you MUST implement them as flyweight objects (go google the Flyweight Pattern if you don’t know it) or else you’ll lose lots of the memory-management and efficiency advantages of a full ES.

Where does the data “live”?

Each Component is merely a classification label (e.g. “Renderable”) and a struct/array/list/whatever of the data relating to it’s purpose; all data lives in Components; ALL data.

How do you do gameobject initialization?

Here’s a fun one – I haven’t mentioned ANYTHING about object/entity intialization. It was really only from trying to use entity systems that I finally realized just how bizarre OOP is when it comes to initialization: you have some “magic methods” (constructor, destructor, finalizer, etc) that have nothing to do with the main description of OOP, but instead are part of a meta-programming that allows you to get your OOP system up and running, and to keep it running, and then to tear it all down again at the end. Until then, I’d not noticed how out-of-place those methods are…

Hats-off to the OOP folks: they integrated their meta-programming so neatly into OOP that in most languages it’s unnoticeable. But I’ve not yet seen the same trick done for an ES – so, get used to the fact that initialization is going to be a bit … “different” …

There’s really a bunch of issues here:

  • what’s the technical term for an entity’s archetype?
  • how do you define the archetypes for your entities?
  • how do you instantiate multiple new entities from a single archetype?
  • how do you STORE in-memory entities so that they can be re-instantiated later on?

What’s the technical term for an entity’s archetype?

There doesn’t seem to be one. Really. There’s a couple floating around, influenced by people’s own backgrounds but I’ve heard quite a few used interchangeably.

My favourites are:

  • template
  • model
  • assemblage

(I actually picked the last one from a thesaurus – looking for equivalents of “class” ;)).

The problem with both “template” and “model” is that they’re both very frequently used generic terms in programming. Entity is pretty good as a term, because it’s hardly used for anything else (and the main obvious competitor is now widely called a “gameobject” by game programmers). I’ve used both, in the past. Interchangeably. (cackle!)

So. “Assemblage”, anyone?

how do you define the archetypes for your entities?
how do you instantiate multiple new entities from a single archetype?
how do you STORE in-memory entities so that they can be re-instantiated later on?

Big topics. Really big. Too big to go into here (ah. Now I know what the next post is going to be about…).

What does the ES bring that cannot be accomplished with an AOP framework?

The simple, facetious, answer is: almost everything.

AOP (Aspect-Oriented Programming) doesn’t really help much to solve the problems that an Entity System solves (although it does solve similar ones that ALSO tend to be present when the ES-related ones are present), and doesn’t provide the new features that you get from an ES (e.g. the improved memory/data-performance).

An ES takes a system where there are many things going on that are all independent, which OOP tangles up together, and pulls them apart and lets them live on their own. It also highly efficiently manages simple interoperation between those disparate aspects of the program, and allows them to be disconnected, reconnected, at will.

AOP takes a system where there are things going on that are fundamentally DEPENDENT, which OOP tangles up together, and allows them to be reasoned about “separately, but together” – you can view the code for logging independent of the code which is being logged, but you have to still reason about them at the same time, you cannot merely ignore one or the other. By definition, different aspects (vested as Components) of an Entity are INdependent, and this whole “together” thing is an irrelevance.

However … AOP certainly helps if you have implemented with OOP something you ideally should have done with an ES, and you want to add new features to it, because the tangled OOP system is going to be a pain to modify without breaking stuff accidentally, and AOP will help you more precisely focus the impact of your changes. But it’s a poor replacement for just implementing the ES you wanted in the first place.

There is also a fairly large area of crossover between “some things you can do with entity systems” and “some things you can do with aspect oriented programming”, mainly because they are both fundamentally data-driven at the function-despatch level (which I’ll come back to later). However, they each use this data-drivenness in very different ways – AOP uses it to react to, and wrap itself around, the code of the program, whereas an ES uses it to react to the data of the program.

Using both together could be really exciting – but I’ve not been brave enough to try that yet myself.

What’s the link between entity systems and SQL/Relational Databases?

You might have guessed this by now – it’s been the theme of most of the answers above, starting from the very beginning of this post.

Mathematically-speaking, an Entity is a database Key, just as you’d see in any RDBMS.

Likewise, from a purely abstracted point of view, the “set of component-instances that comprise Entity #7742” is, literally, a database Query.

THIS is why I said at the start that, ideally, you do NOT want to store your component-instances as a list inside a struct/class representation of each Entity. Fundamentally, that set is NOT defined as a list (a list is a static thing, it’s members don’t change without you changing them), it’s defined as a query (whose members are always changing, whether you want them to or not), and using one where really you wanted the other tends to cause problems in the long term.

Obviously, you can use Lists as a simple form of query (that query being “what things are currently in this list”), but that’s a rather poor and inflexible kind of query. Life is much more interesting if you embrace the dynamicity of the query, and fetch the components (and, hence, the VALUES of the data…) by running a query every time you want one or more of them.

This is a fairly star-gazing view of how to make games: the game is just one giant database, running dynamic queries all the time. Current performance, even of fast RDBMS’s, is just way too slow to be running thousands of queries per frame on a home PC.

However, these articles are about ES’s for massively multiplayer online game development, not just standard game development, and that changes two things in particular:

1. Most of the game is NOT running on home PC’s, it’s running on arbitrarily beefy server-farms that are already running bajillions of QL queries (nearly always SQL these days, but any of MS SQL Server, Oracle, or MySQL).

2. The data is much much more important than rendering speed; we have almost no problem making incredibly beautiful 3D rendered landscapes, but managing the data to make those landscapes act and react as if they were real (i.e. world-logic, game-logic, etc) is something we still find rather hard

A new thought for the day…

Think what you can do with an ES if you deploy it on an MMO server farm, and go the full monty by making all your entity/component aggregations stored merely as SQL queries. Here’s some to start you off…

1. No more pain from “Relational vs OOP”

One of the slowest parts of MMO server performance is translating OOP objects into RDBMS tables so that the database can save them, and then translating them back again when the game needs to read them. This also wastes large amounts of programmer time on boring, annoying, tricky to maintain code to handle the serialization processes.

2. Massive increase in parallelization for free

If you make all processing data-driven, and you have no data-structures that have to remain synchronized, then it becomes a lot easier to “just add more CPU’s” to increase runtime performance…

3. Where else could you use SELECT instead of data structures?

When each System has to do it’s processing, it’s probably going to iterate over “all Entities that have my Component”. Is that something you can store easily in a standard data-structure? Or is it better off as a QL query? And what else can you achieve if you start doing your processing this way? (hint: there’s some nice benefits for the low-level network programming here…)

Entity Systems are the Future of MMOs Part 4

Massively Multiplayer Entity Systems: Introduction

So, what’s the connection between ES and MMO, that I’ve so tantalisingly been dangling in the title of the last three posts? (start here if you haven’t read them yet).

The short answer is: it’s all about data. And data is a lot harder than most people think, whenever you have to deal with an entire system (like an MMO) instead of just one consumer of a system (like the game-client, which is the only part of an MMO that traditional games have).

Obviously, we need to look at it in a lot more detail than that. First, some background…

Massively Multiplayer Game Development 101

There’s a few key things you need to be aware of in MMO development. Many professional game developers know some or all of these already, but seeing as I’ve even met MMO developers who didn’t know them all, and much of what I’m going to say later on won’t make sense without it, I’m going to do a quick recap. Bear with me; I’ll have to do some gross generalization to keep this short (so it won’t be 100% true or accurate).

1. The vast majority of the cost of MMO development is content

Content is:
– quests (missions, storylines, scripted events)
– 3D areas (meshes, textures and logic for: zones, dungeons, towns, landscapes)
– loot (item graphics, drop rates, item stats, item abilities)

Content is NOT:
– Fancy 3D graphics
– Physics engines
– AI
– Core game rules

…which tend to make up the bulk of non-MMO games.

As Raph Koster (amongst others, but IIRC Raph was one of the first to come up with a clear concise description) pointed out close to 10 years ago, the rate at which players consume content vastly excedes the rate at which developers generate it – you have perhaps 50 people working purely on content generation on a modern MMO, and you have perhaps 500,000 people consuming it. The problem is, those 500,000 use Thottbot, so they *share* their discoveries, and consume at a rate proportional to the square of their number, whereas it’s generally produced at a rate more directly proportional to the number of developers.

There are many ways to work around this issue, but most of them end up producing or managing vast amounts of content (they just get more cunning in exactly how that content is generated).

2. The vast majority of the development of an MMO takes place AFTER launch

The ten-year-old MMO’s have been releasing expansions and content updates every 6 to 18 months; modern MMO’s release new content every 3 to 12 months. “New content” in this context generally means entirely new 3D areas with entirely new quests and entirely new items, not to mention entirely new special abilities and new plotlines. i.e. complete “miniature MMOs”.
The only bits you don’t need to keep rewriting are the technology, although nearly all MMOs have done minor updates throughout their lifetime, usually when a new expansion pack is released as a retail boxed product (if you buy and install the expansion, not only do you get the bonus content, but all the “old” content becomes higher resolution / more pretty / added sparkly bits). Although … I long wished there was more updating of tech, and three major MMOs are currently doing huge updates: Ultima Online (1997) recently massively renovated their 10-year old graphics as Kingdom Reborn, Eve Online (2001) just completed their “shininess and detailed spaceships with added humanoids” update known as Trinity, and Anarchy Online (2001) recently previewed massive sweeping changes to their very poor detail and draw distance client (they say “the current engine was designed before there really were GPUs to utilize” but that is blatantly false as the GeForce had been on sale for almost 2 years when they launched, and the TNT,Voodoo, et al for years before that. Yes, I was bitter that when it launched the most recent hardware it supported was 5 years old :)). All represent major changes to the look and feel of the games – it’s hard to overestimate the visual impact of these. Runescape did their mega update (“Runescape 2”) a couple of years ago.

However … all are bringing games that were NOT cutting edge at launch up to a standard that is still well short of what is cutting edge now. This is important to understand: graphical quality is (according to what the successful MMO’s deploy) definitely not the main selling point for these games, unlike almost all other successful games you can possibly buy.

So … what is that “development” that takes place after launch? It’s content, not engine. And even when it’s engine (better graphics, better physics) it’s always a minimal improvement by the standards of standalone PC and console titles of the time.

For reference, many MMO’s after launch end up with LARGER development teams than they had in the 3-5 years of development leading up to the launch. All that extra content requires a lot of people (not to mention keeping all the old content working, updating it where it conflicts with new content, etc).

On top of all that, though, there is the issue of customer support. When you launch a traditional game, that’s it. Done. Over the last 15 years there’s been a trend towards launching occasional “patches” and even minor content updates – but mostly bugfixes – which, incidentally, I suspect has been largely driven by publishers learning from the MMOs: releasing a content patch for an old game is a good way to get extra marketing / publicity and increase some sales. Bethesda’s TES4/Oblivion even went as far as to charge for the patches.

MMO’s require a lot more work than that: since MMO’s are all monetized off continuous play (i.e. the more each player plays, the more money the publisher makes), either through monthly subscriptions or through in-game commerce, it is imperative to keep all the players playing as long as possible. If a player plays your MMO for 12 months instead of 6, you’ll make twice as much profit; if they play your console title for 12 months instead of 6, you’ll make no more money and will probably cannibalize your sales of the sequel.

So. Total lifetime development cost is a lot more important, financially, to an MMO than the pre-launch development cost.

3. The way the core logic works now is not how it will work forever

Sooner or later, you nerf.

Usually because you(r players) discover a disproportionately powerful game tactic in PvP that you didn’t think of which is unbalancing and ruining the game, and so you “have” to fix it.

Sooner or later, you choose to break every absolute rule of your game logic, because a new expansion wants to slightly redefine and “freshen” the core game.

And that means you have to be able to break every rule you ever hardcoded into the game-logic. Worse, it means you have to be able to handle the fallout (all the bugs that the change introduces, plus all the invisible bugs that were originally there but had no noticeable effect and now suddenly have visible effect, the new security holes, etc).

Since the ongoing development of the game (post launch) is greater than the initial development in scope and cost, over the lifetime of the game it is more important to make it easy to change the core logic – and to react to side effects of that change – than to be able to make the core logic easily in the first place.

4. Even a moderately successful MMO generates gigabytes of data every 24 hours

The progress of every player of the MMO has to be uniquely independently tracked, so that the game can remember for each player which quests they’ve completed, which equipment they have, etc. With 100,000 players, that data racks up quickly. A lot of it can be thrown away every day (for instance, you don’t generally need the history of how many hitpoints you had at the end of every day), but a lot of it has to be kept forever (whether you completed a given quest, and for some quests how exactly you completed it).

However, the trend at the moment is towards keeping ALL this data, in the form of historical records of your personal game experience – e.g. the automatic “blog” that is created whilst you play Vanguard, which e.g. updates every time you level up, or kill a monster, or die, etc.

This latter kind of data alone is generated at the rate of around 30Gb every 24 hours.

And any of that data that gets used in-game (e.g. even if just referenced in a conversation with an NPC) has to be programmatically accessible.

Ultimately, MMOs have to store, retrieve, and update vast databases. There is a huge decades-old industry that specializes in providing software to manage databases of this size and larger, but MMO developers don’t like SQL and Relational programming. This is a real problem – relational databases can handle the load, but relational programming is fundamentally incompatible with Object-Oriented programming. The net effect is that programmers who have to write their data to disk find it boring, difficult, and irritating to do – and that leads to mistakes and greatly increased bugs, as well as reduced functionality (because no-one wants to write or add to the code to add the new features more than they absolutely have to).

MMO Development Priorities

The net effect of these aspects of MMO development is that the long term profitability of an MMO can be greatly affected by a bunch of simple issues:

  • How much effort is required to change the data used to describe an in-game item
  • How much effort is required to add (or remove) new (old) types of in-game item
  • How re-usable is the content
  • How easy it is in practice (i.e. how much coding is needed) to re-use re-usable content
  • How much specialist knowledge of the game code, overall game design, and details of the game systems is needed to modify the content and logic (can new team members be effective as the team who originally wrote the game pre-launch?)
  • How exportable is the data generated by playing the game (progress, achievements, player-history, etc)
  • How analysable is the game-data generated by playing (to make decisions about what to change, and check that game improvements have improed things)
  • How modifiable the core-content is
  • How easy it is to change individual rules and check the side-effects of the changes
  • How many of all the above changes can be done WITHOUT requiring a programmer (can designers change code themselves? can artists?)
  • How much can third-party specialist systems be utilised for server-side service provision

Leading to a few rules of thumb that are often adopted by commercial MMOs:

  1. Use commercial databases for all persistent data-storage
  2. Use Relational Databases and allow arbitrary general data requests
  3. Implement as much as possible of the game-logic as raw data rather than as compiled data (and preferably as data rather than source code)
  4. Use standard but simple to learn scripting languages where data isn’t expressive enough
  5. Do lots and lots of testing during development
  6. Do even more testing post-launch EVERY SINGLE TIME you consider changing ANYTHING on the live servers

Some of those aren’t very effective (too vague), others are horrifically expensive (it takes a lot of people to “test EVERYTHING” every time you make a change to a live game). None of them are great for performance in and of themselves (although they can be made highly performant, that requires extra work), and none of them are “programmer friendly” – in fact, they’re all deliberately programmer UNfriendly, being in there for the benefit of non-programmers.

NB: this is in no way a comprehensive or exhaustive list; I’m trying to give merely a flavour of the thing here for people who aren’t familiar with typical MMO dev processes. I don’t know any real MMO that faces only those challenges and uses only those rules of thumb, but they are indicative of what is used, and very very roughly explain why those things are used.

And so on to Entity Systems, and how they can affect the typical MMO development process by helping with problems or making the current solutions more programmer-friendly… (which is going to be Part 5. This is getting long enough already).

Entity Systems are the Future of MMOs Part 5

(Start by reading Entity Systems are the Future of MMOs Part 1)

It’s been a long time since my last post on this topic. Last year, I stopped working for a big MMO publisher, and since then I’ve been having fun doing MMO Consultancy (helping other teams write their games), and iPhone development (learning how to design and write great iPhone apps).

Previously, I posed some questions and said I’d answer them later:

  • how do you define the archetypes for your entities?
  • how do you instantiate multiple new entities from a single archetype?
  • how do you STORE in-memory entities so that they can be re-instantiated later on?

Let’s answer those first.

A quick warning…

I’m going to write this post using Relational terminology. This is deliberate, for several reasons:

  • It’s the most-correct practical way of describing runtime Entities
  • It’s fairly trivial to see how to implement this using static and dynamic arrays – the reverse is not so obvious
  • If you’re working on MMO’s, you should be using SQL for your persistence / back-end – which means you should already be thinking in Relations.
…and a quick introduction to Relational

If you know literally nothing about Relational data, RDBMS’s, and/or SQL (which is true of most game programmers, sadly), then here’s the idiot’s guide:

  1. Everything is stored either in arrays, or in 2-dimensional arrays (“arrays-of-arrays”)
  2. The index into the array is explicitly given a name, some text ending in “_id”; but it’s still just an array-index: an increasing list of integers starting with 0, 1, 2, 3 … etc
  3. Since you can’t have Dictionaries / HashMaps, you have to use 3 arrays-of-arrays to simulate one Dictionary. This is very very typical, and so obvious you should be able to understand it easily when you see it below. I only do it twice in this whole blog post.
  4. Where I say “table, with N columns”, I mean “a variable-length array, with each element containing another array: a fixed-size array of N items”
  5. Where I say “row”, I mean “one of the fixed-size arrays of N items”
  6. Rather than index the fixed-size arrays by integer from 0…N, we give a unique name (“column name”) to each index. It makes writing code much much clearer. Since the arrays are fixed-size, and we know all these column names before we write the program, this is no problem.

Beyond that … well, go google “SQL Tutorial” – most of them are just 1 page long, and take no more than 5 minutes to read through.

How do you store all your data? Part 2: Runtime Entities + Components (“Objects”)

We’re doing part 2 first, because it’s the bit most of us think of first. When I go onto part 1 later, you’ll see why it’s “theoretically” the first part (and I called it “1”), even though when you write your game, you’ll probably write it second.

Table 3: all components

(yes, I’m starting at 3. You’ll see why later ;))

Table 3: components
component_id official name human-readable description table-name

There are N additional tables, one for each row in the Components table. Each row has a unique value of “table-name”, telling you which table to look at for this component. This is optional: you could instead use an algorithmic name based on some criteria like the official_name, or the component_id – but if you ever change the name of a component, or delete one and re-use the id, you’ll get problems.

Table 4: all entities / entity names
Table 4 : entities
entity_id human-readable label FOR DEBUGGING ONLY

(really,you should only have 1 column in this table – but the second column is really useful when debuggin your own ES implementation itself!)

…which combines with:…

Table 5: entity/component mapping
Table 5 : entity_components
entity_id component_id component_data_id

…to tell you which components are in which entity.

Technically, you could decide not to bother with Table 4; just look up the “unique values of entity_id from table 5” whenever you want to deal with Table 4. But there are performance advantages for it – and you get to avoid some multi-threading issues (e.g. when creating a new entity, just create a blank entity in the entity table first, and that fast atomic action “reserves” an entity_id; without Table 4, you have to create ALL the components inside a Synchronized block of code, which is not good practice for MT code).

Tables 6,7,8…N+5: data for each component for each Entity
Table N+5 : component_data_table_N
component_data_id [1..M columns, one column for each piece of data in your component]

These N tables store all the live, runtime, data for all the entity/component pairs.

How do you store all your data? Part 1: Assemblages (“Classes”)

So … you want to instantiate 10 new tanks into your game.

How?

Well, you could write code that says:


int newTank()
{
int new_id = createNewEntity();

// Attach components to the entity; they will have DEFAULT values

createComponentAndAddTo( TRACKED_COMPONENT, new_id );
createComponentAndAddTo( RENDERABLE_COMPONENT, new_id );
createComponentAndAddTo( PHYSICS_COMPONENT, new_id );
createComponentAndAddTo( GUN_COMPONENT, new_id );

// Setup code that EDITS the data in each component, e.g:
float[] gunData = getComponentDataForEntity( GUN_COMPONENT, new_id );
gunData[ GUN_SIZE ] = 500;
gunData[ GUN_DAMAGE ] = 10000;
gunData[ GUN_FIRE_RATE ] = 0.001;
setComponentDataForEntity( GUN_COMPONENT, new_id, gunData );


return new_id;
}

…and this is absolutely fine, so long as you remember ONE important thing: the above code is NOT inside a method “because you wanted it in an OOP class”. It’s inside a method “because you didn’t want to type it out every time you have a place in your code where you instantiate tanks”.

i.e. IT IS NOT OOP CODE! (the use of “methods” or “functions” is an idea that predates OOP by decades – it is coincidence that OOP *also* uses methods).

Or, in other words, if you do the above:

NEVER put the above code into a Class on its own; especially NEVER NEVER split the above code into multiple methods, and use OOP inheritance to nest the calls to “createComponet” etc.

But … it means that when you decide to split one Component into 2 Components, you’ll have to go through the source code for EVERY kind of game-object in your game, and change the source, then re-compile.

A neater way to handle this is to extend the ES to not only define “the components in each entity” but also “templates for creating new entities of a given human-readable type”. I previously referred to these templates as “assemblages” to avoid using the confusing term “template” which means many things already in OOP programming…

An assemblage needs:

Table 1: all Assemblages
Table 1 : assemblages
assemblage_id default human-readable label (if you’re using that label in Table 1 above) official name human-readable description
Table 2: assemblage/component mapping
Table 2 : assemblage_components
assemblage_id component_id

This table is cut-down version of Table 5 (entity/component mapping). This table provides the “template” for instantiating a new Entity: you pick an assemblage_id, find out all the component_id’s that exist for it, and then create a new Entity and instantiate one of each of those components and add it to the entity.

Table 3: all components
Table 3: components
component_id official name human-readable description table-name

This is the same table from earlier (hence the silly numbering, just to make sure you noticed ;)) – it MUST be the same data, for obvious reasons.

Things to note

DataForEntity( (entity-id) ) – fast lookup

If you know the entity-id, you may only need one table lookup to get the data for an entire component (Table5 is highly cacheable – it’s small, doesn’t change, and has fixed-size rows).

Splitting Table 5 for performance or parallelization

When your SQL DB is too slow and you want to split to multiple DB servers, OR you’re not using SQL (doing it all in RAM) and want to fit inside your CPU cache, then you’ll split table 5 usually into N sub-tables, where N = number of unique component_id’s.

Why?

Because you run one System at a time, and each System needs all the components with the same component_id – but none of the components without that id.

Isolation

The entire data for any given system is fully isolated into its own table. It’s easy to print to screen (for debugging), serialize (for saving / bug reports), parallelize (different components on different physical DB servers)

Metadata for editing your Assemblages and Entities

a.k.a. “Programmer/Designers: take note…”

It can be tempting to add extra columns to the Entity and Assemblage tables. Really, you shouldn’t be doing this. If you feel tempted to do that, add the extra data as more COMPONENTS – even if the data is NOTHING to do with your game (e.g. “name_of_designer_who_wrote_this_assemblage”).

Here’s a great feature of Entity Systems: it is (literally) trivial for the game to “remove” un-needed information at startup. If, for instance, you have vast amounts of metadata on each entity (e.g. “name of author”, “time of creation”, “what I had for lunch on the day when I wrote this entity”) – then it can all be included and AUTOMATICALLY be stripped-out at runtime. It can even be included in the application, but “not loaded” at startup – so you get the benefits of keeping all the debug data hanging around, with no performance overhead.

You can’t do that with OOP: you can get some *similar* benefits by doing C-Header-File Voodoo, and writing lots of proprietary code … but … so much is dependent upon your header files that unless you really know what you’re doing you probably shouldn’t go there.

Another great example is Subversion / Git / CVS / etc metadata: you can attach to each Entity the full Subversion metadata for that Entity, by creating a “SubversionInformation” System / Component. Then at runtime, if something crashes, load up the SubversionInformation system, and include it in the crash log. Of course, the Components for the SubversionInformation system aren’t actually loader yet – because the system wasn’t used inside the main game. No problem – now you’ve started the system (in your crash-handler code), it’ll pull in its own data from disk, attach it to whatever entities are in-memory, and all works beautifully.

Wrapping up…

I wanted to cover other things – like transmitting all this stuff over the network (and maybe cover how to do so both fast and efficiently) – but I realise now that this post is going to be long enough as it is.

Next time, I hope to talk about that (binary serialization / loading), and editors (how do you make it easy to edit / design your own game?).

Entity ID’s: how big, using UUIDs or not, why, etc?

This has come up a few times, and I ended up replying on Twitter:

But that’s a crappy way to find things later, so I made a quick-and-dirty infographic with a few key points:

Docs-entityID

I’m working on my own Entity System; want to follow it?

Refactoring Game Entities with Components

Up until fairly recent years, game programmers have consistently used a deep class hierarchy to represent game entities. The tide is beginning to shift from this use of deep hierarchies to a variety of methods that compose a game entity object as an aggregation of components. This article explains what this means, and explores some of the benefits and practical considerations of such an approach. I will describe my personal experience in implementing this system on a large code base, including how to sell the idea to other programmers and management.

GAME ENTITIES

Different games have different requirements as to what is needed in a game entity, but in most games the concept of a game entity is quite similar. A game entity is some object that exists in the game world, usually the object is visible to the player, and usually it can move around.

Some example entities:

  • Missile
  • Car
  • Tank
  • Grenade
  • Gun
  • Hero
  • Pedestrian
  • Alien
  • Jetpack
  • Med-kit
  • Rock

Entities can usually do various things. Here are some of the things you might want the entities to do

  • Run a script
  • Move
  • React as a rigid body
  • Emit Particles
  • Play located audio
  • Be packed up by the player
  • Be worn by the player
  • Explode
  • React to magnets
  • Be targeted by the player
  • Follow a path
  • Animate

TRADITIONAL DEEP HIERARCHIES


The traditional way of representing a set of game entities like this is to perform an object-oriented decomposition of the set of entities we want to represent. This usually starts out with good intentions, but is frequently modified as the game development progresses – particularly if a game engine is re-used for a different game. We usually end up with something like figure 1, but with a far greater number of nodes in the class hierarchy.

As development progresses, we usually need to add various points of functionality to the entities. The objects must either encapsulate the functionality themselves, or be derived from an object that includes that functionality. Often, the functionality is added to the class hierarchy at some level near the root, such as the CEntity class. This has the benefit of the functionality being available to all derived classes, but has the downside of the associated overhead also being carried by those classes.

Even fairly simple objects such as rocks or grenades can end up with a large amount of additional functionality (and associated member variables, and possibly unnecessary execution of member functions). Often, the traditional game object hierarchy ends up creating the type of object known as “the blob”. The blob is a classic “anti-pattern” which manifests as a huge single class (or a specific branch of a class hierarchy) with a large amount of complex interwoven functionality.

While the blob anti-pattern often shows up near the root of the object hierarchy, it will also show up in leaf nodes. The most likely candidate for this is the class representing the player character. Since the game is usually programmed around a single character, then the object representing that character often has a very large amount of functionality. Frequently this is implemented as a large number of member functions in a class such as CPlayer.

The result of implementing functionality near the root of the hierarchy is an overburdening of the leaf objects with unneeded functionality. However, the opposite method of implementing the functionality in the leaf nodes can also have unfortunate consequence. Functionality now becomes compartmentalized, so that only the objects specifically programmed for that particular functionality can use it. Programmers often duplicate code to mirror functionality already implemented in a different object. Eventually messy re-factoring is required by re-structuring the class hierarchy to move and combine functionality.

Take for example the functionality of having an object react under physics as a rigid body. Not every object needs to be able to do this. As you can see in figure 1, we just have the CRock and the CGrenade classes derived from CRigid. What happens when we want to apply this functionality to the vehicles? You have to move the CRigid class further up the hierarchy, making it more and more like the root-heavy blob pattern we saw before, with all the functionality bunched in a narrow chain of classes from which most other entity classes are derived.

AN AGGREGATION OF COMPONENTS

The component approach, which is gaining more acceptance in current game development, is one of separating the functionality into individual components that are mostly independent of one another. The traditional object hierarchy is dispensed with, and an object is now created as an aggregation (a collection) of independent components.

Each object now only has the functionality that it needs. Any distinct new functionality is implemented by adding a component.

A system of forming an object from aggregating components can be implemented in one of three ways, which may be viewed as separate stages in moving from a blob object hierarchy to a composite object.

OBJECT AS ORGANIZED BLOB

A common way of re-factoring a blob object is to break out the functionality of that object into sub-objects, which are then referenced by the first object. Eventually the parent blob object can mostly be replaced by a series of pointers to other objects, and the blob object’s member functions become interface functions for the functions of those sub-objects.

This may actually be a reasonable solution if the amount of functionality in your game objects is reasonably small, or if time is limited. You can implement arbitrary object aggregation simply by allowing some of the sub-objects to be absent (by having a NULL pointer to them). Assuming there are not too many sub-objects, then this still allows you the advantage of having lightweight pseudo-composite objects without having to implement a framework for managing the components of that object.

The downside is that this is still essentially a blob. All the functionality is still encapsulated within one large object. It is unlikely you will fully factor the blob into purely sub-objects, so you will still be left with some significant overhead, which will weight down your lightweight objects. You still have the overhead of constantly checking all the NULL pointers to see if they need updating.

OBJECT AS COMPONENT CONTAINER

The next stage is to factor out each of the components (the “sub-objects” in the previous example) into objects that share a common base class, so we can store a list of components inside of an object.

This is an intermediate solution, as we still have the root “object” that represents the game entity. However, it may be a reasonable solution, or indeed the only practical solution, if a large part of the code base requires this notion of a game object as a concrete object.

Your game object then becomes an interface object that acts as a bridge between the legacy code in your game, and the new system of composite objects. As time permits, you will eventually remove the notion of game entity as being a monolithic object, and instead address the object more and more directly via its components. Eventually you may be able to transition to a pure aggregation.

OBJECT AS A PURE AGGREGATION

In this final arrangement, an object is simply the sum of its parts. Figure 2 shows a scheme where each game entity is comprised of a collection of components. There is no “game entity object” as such. Each column in the diagram represents a list of identical components, each row can be though of as representing an objects. The components themselves can be treated as being independent of the objects they make up.

PRACTICAL EXPERIENCE

I first implemented a system of object composition from components when working at Neversoft, on the Tony Hawk series of games. Our game object system had developed over the course of three successive games until we had a game object hierarchy that resembled the blob anti-pattern I described earlier. It suffered from all the same problems: the objects tended to be heavyweight. Objects had unnecessary data and functionality. Sometimes the unnecessary functionality slowed down the game. Functionality was sometimes duplicated in different branches of the tree.

I had heard about this new-fangled “component based objects” system on the sweng-gamedev mailing list, and decided it sounded like a very good idea. I set to re-organizing the code-base and two years later, it was done.

Why so long? Well, firstly we were churning out Tony Hawk games at the rate of one per year, so there was little time between games to devote to re-factoring. Secondly, I miscalculated the scale of the problem. A three-year old code-base contains a lot of code. A lot of that code became somewhat inflexible over the years. Since the code relied on the game objects being game objects, and very particular game objects at that, it proved to be a lot of work to make everything work as components.

EXPECT RESISTANCE

The first problem I encountered was in trying to explain the system to other programmers. If you are not particularly familiar with the idea of object composition and aggregation, then it can strike you as pointless, needlessly complex, and unnecessary extra work. Programmers who have worked with the traditional system of object hierarchies for many years become very used to working that way. They even become very good at working that way, and manage to work around the problems as they arise.

Selling the idea to management is also a difficult. You need to be able to explain in plain words exactly how this is going to help get the game done faster. Something along the lines of:

Whenever we add new stuff to the game now, it takes a long time to do, and there are lots of bugs. If we do this new component object thing, it will let us add new stuff a lot quicker, and have fewer bugs.”

My approach was to introduce it in a stealth manner. I first discussed the idea with a couple of programmers individually, and eventually convinced them it was a good idea. I then implemented the basic framework for generic components, and implemented one small aspect of game object functionality as a component.

I then presented this to the rest of the programmers. There was some confusion and resistance, but since it was implemented and working there was not much argument.

SLOW PROGRESS

Once the framework was established, the conversion from static hierarchy to object composition happened slowly. It is thankless work, since you spend hours and days re-factoring code into something that seems functionally no different to the code it replaces. In addition, we were doing this while still implementing new features for the next iteration of the game.

At an early point, we hit the problem of re-factoring our largest class, the skater class. Since it contained a vast amount of functionality, it was almost impossible to re-factor a piece at a time. In addition, it could not really be re-factored until the other object systems in the game conformed to the component way of doing things. These in turn could not be cleanly refactored as components unless the skater was also a component.

The solution here was to create a “blob component.” This was a single huge component, which encapsulated much of the functionality of the skater class. A few other blob components were required in other places, and we eventually shoehorned the entire object system into a collection of components. Once this was in place, the blob components could gradually be refactored into more atomic components.

RESULTS

The first results of this re-factoring were barely tangible. But over time the code became cleaner and easier to maintain as functionality was encapsulated in discreet components. Programmers began to create new types of object in less time simply by combining a few components and adding a new one.

We created a system of data-driven object creation, so that entirely new types of object could be created by the designers. This proved invaluable in the speedy creation and configuration of new types of objects.

Eventually the programmers came (at different rates) to embrace the component system, and became very adept at adding new functionality via components. The common interface and the strict encapsulation led to a reduction in bugs, and code that that was easier to read, maintain and re-use.

IMPLEMENTATION DETAILS

Giving each component a common interface means deriving from a base class with virtual functions. This introduces some additional overhead. Do not let this turn you against the idea, as the additional overhead is small, compared to the savings due to simplification of objects.

Since each component has a common interface, it is very easy to add additional debug member functions to each component. That made it a relatively simple matter to add an object inspector that could dump the contents of the components of a composite object in a human readable manner. Later this would evolve into a sophisticated remote debugging tool that was always up to date with all possible types of game object. This is something that would have been very tiresome to implement and maintain with the traditional hierarchy.

Ideally, components should not know about each other. However, in a practical world, there are always going to be dependencies between specific components. Performance issues also dictate that components should be able to quickly access other components. Initially we had all component references going through the component manager, however when this started using up over 5% of our CPU time, we allowed the components to store pointers to one another, and call member functions in other components directly.

The order of composition of the components in an object can be important. In our initial system, we stored the components as a list inside a container object. Each component had an update function, which was called as we iterated over the list of components for each object.

Since the object creation was data driven, it could create problems if the list of components is in an unexpected order. If one object updates physics before animation, and the other updates animation before physics, then they might get out of sync with each other. Dependencies such as this need to be identified, and then enforced in code.

CONCLUSIONS

Moving from blob style object hierarchies to composite objects made from a collection of components was one of the best decisions I made. The initial results were disappointing as it took a long time to re-factor existing code. However, the end results were well worth it, with lightweight, flexible, robust and re-usable code.

Game Object Structure: Inheritance vs. Aggregation

By Kyle Wilson
Wednesday, July 03, 2002

Every game engine I’ve encountered has had some notion of a game object, or a scene object, or an entity.  A game object may be an animated creature, or an invisible box that sets off a trigger when entered, or an invisible hardpoint to which a missile attaches.  In general, though, there will be a game object class which exposes an interface, or multiple interfaces, to the systems that handle collision, rendering, triggering, sound, etc.

(c) FreeFoto.comAt Interactive Magic, and later at HeadSpin/Cyan, I worked with inheritance-based game objects.  There was a base game object class, from which were derived other object types.  For example, dynamic objects derived from game objects, and animated objects derived from dynamic objects, and so forth.  When I got to iROCK, I found a similar scheme, but with some differences that I’ll discuss in a minute.

There are several problems with a game object design based on inheritance.  Some problems can be worked around (with varying degrees of difficulty).  Some problems are inherent in an inheritance-based design.

  • The Diamond of Death.  What do you do if trigger objects are derived from game objects, and dynamic objects are derived from game objects, but you want a dynamic trigger object?  In C++, you have to make your trigger objects and dynamic objects inherit from game objects virtually.  Virtual inheritance is poorly understood by most programmers, makes maintenance more difficult, and adds subtle inefficiencies to your code.  (Read [7] for details.  Also see [6], Item 43, for other problems with multiple inheritance.)  Inheritance handles overlapping categories poorly.
  • Pass-Thru Enforcement.  In a game object hierarchy — more than most class hierarchies, I think — it’s useful to have functions perform class specific actions, then pass the function call down to a parent class.  For example, at HeadSpin, our game object base class declared a virtual function called Update.  Update was intended to do everything a class required before being drawn.  In the root game object class, it refreshed the current world space transform for the game object.  In derived classes, Update might change other state settings, then call Update in the parent class.  But C++ doesn’t offer any convenient mechanism for requiring that a virtual function recurse down through base class implementations of itself.  Every time we added a new class to the engine, at least one function pass-thru got left out, and had to be caught in debugging.
    This problem can be ameliorated somewhat if you don’t publicly expose virtual functions, but instead use the Template Method pattern[3], or what Herb Sutter calls the “Nonvirtual Interface idiom”[8].  That is, have a base class consisting only of public non-virtual functions which call private virtual functions.  The non-virtual functions can perform whatever base-class-specific actions they require before calling the private virtuals.  This still won’t help, however, with deep class hierarchies where leaf classes need to pass through function calls to intermediate parent classes, not just the root class.
  • Unintended Consequences.  A corollary to the Pass-Thru Enforcement problem is that when a virtual function call recurses down the class hierarchy, it’s easy to lose track of which actions are being performed for which classes.  In [5], Herb Marselas writes that since Ensemble used an inheritance-based game object hierarchy for Age of Empires II, “functionality can be added or changed in a single place in the code to affect many different game units. One such change inadvertently added line-of-sight checking for trees,” which was a performance problem, since an AOE2 level generally contained a large number of trees.
  • Dependencies.  Inheritance is one of the tightest couplings there is in C++.  As such, it affects not just program logic, but also the physical design of a program.  Inheritance always creates compile- and link-time dependencies in your code.  To compile a file using any game object, the parser must also load the header files containing all its ancestors.  The linker must resolve all dependencies to the same.  If any game object needs to know about its descendents, then cyclic dependencies arise, and proper levelization becomes impossible.  (See [4].)
  • Difficulty in Comprehension.  To understand the behavior of any class, you have to open other files and learn the behavior of its ancestors.
  • Interface Bloat.  Monolithic classes tend to develop large interfaces to cover the host of purposes they serve.  By the time I left Cyan, our scene object base class had a class definition alone that was over four hundred lines of flag enums and function declarations for physics, graphics, sound, animation and stream I/O.  And the interface would have been bloated further by null virtual functions used by derived classes if we hadn’t instead resorted sometimes to just checking type-ids and doing static_casts to derived types.
    We partly solved this problem at iROCK by having multiple class hierarchies, instead of just one.  What would normally be one game object becomes three, a game object, a scene object, and a sound object, all in separate modules.  This is an improvement in principle, but in practice, independence of the different modules was never well enforced.  In the end, game objects included scene object headers, sound objects included game object headers, and the code was rife with the cyclic dependencies that John Lakos so deplores.

(c) FreeFoto.comSo if an inheritance-based game object design is riddled with problems, what is a better approach?  In redesigning the Plasma engine used by HeadSpin/Cyan, the software engineering team opted to flatten the game object hierarchy down to a single game object class.  This class aggregated some number of components which supported functionality previously supported by derived game objects.

In a post to Sweng-Gamedev back in early 2001[1] — around the time Cyan started rearchitecting Plasma — Scott Bilas of Gas Powered Games described changing the Dungeon Siege engine from a “static class hierarchy” to a “component based” design.  In the same thread[2], Charles Bloom of Oddworld described the Munch’s Oddysee class design as being similar to that of Dungeon Siege.

From these data points, I’m willing to interpolate a trend.  If moving from class hierarchies to containers of components for game objects is a trend in game development, it mirrors a broader shift in the C++ development community at large.  The traditional game object hierarchy sounds like what Herb Sutter characterizes as “mid-1990s-style inheritance-heavy design” [8].  (Sutter goes on to warn against overuse of inheritance.)  In Design Patterns, the gang of four recommends only two principles for object oriented design:  (1) program to an interface and not to an implementation and (2) favor object composition over class inheritance [3].

Component-based game objects are cleaner and more powerful than game objects based on inheritance.  Components allow for better encapsulation of functionality.  And components are inherently dynamic — they give you the power to change at runtime state which could only be changed at compile time under an inheritance-based design.  The use of inheritance in implementing game object functionality is attractive, but eventually limiting.  A component-based design is to be preferred.

The Entity-Component-System – An awesome game-design pattern in C++ (Part 1)

by Tobias Stein on 11/22/17 10:25:00 am   Featured Blogs
5 comments Share on Twitter

   RSS


The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.


Hi Folks.

This is actually my first post on gamasutra 🙂 I am here pretty much every day and checkout cool posts, today is gonna be the day I add one by myself 🙂 You will find the origial post here.

In this article I want to talk about the Entity-Component-System (ECS). You can find a lot of information about the matter in the internet so I am not going to deep into explanation here, but talking more about my own implementation.

First things first. You will find the full source code of my ECS in my github repository.

An Entity-Component-System – mostly encountered in video games – is a design pattern which allows you great flexibility in designing your overall software architecture[1]. Big companies like Unity, Epic or Crytek in-cooperate this pattern into their frameworks to provide a very rich tool for developers to build their software with. You can checkout these posts to follow a broad discussion about the matter[2,3,4,5].

If you have read the articles I mentioned above you will notice they all share the same goal: distributing different concerns and tasks between Entities, Components and Systems. These are the three big players in this pattern and are fairly loose coupled. Entities are mainly used to provide a unique identifier, make the environment aware of the existence of a single individual and function as a sort of root object that bundles a set of components. Components are nothing more than container objects that do not possess any complex logic. Ideally they are simple plain old data objects (POD’s). Each type of a component can be attached to an entity to provide some sort of a property. Let’s say for example a “Health-Component” can be attached to an entity to make it mortal by giving it health, which is not more than an integer or floating point value in memory.

Up to this point most of the articles I came across agree about the purpose and use of entity and component objects, but for systems opinions differ. Some people suggest that systems are only aware of components. Furthermore some say for each type of component there should be a system, e.g. for “Collision-Components” there is a “Collision-System”, for “Health-Components” there is a “Health-System” etc. This approach is kind of rigid and does not consider the interplay of different components. A less restrictive approach is to let different systems deal with all components they should be concerned with. For instance a “Physics-Systems” should be aware of “Collision-Components” and “Rigidbody-Components”, as both probably contain necessary information regarding physics simulation. In my humble opinion systems are “closed environments”. That is, they do not take ownership of entities nor components. They do access them through independent manager objects, which in turn will take care of the entities and components life-cycle.

This raises an interesting question: how do entities, components and systems communicate with each other, if they are more or less independent of each other? Depending on the implementation the answer differs. As for the implementation I am going to show you, the answer is event sourcing[6]. Events are distributed through an “Event-Manager” and everyone who is interested in events can listen to what the manager has to say. If an entity or system or even a component has an important state change to communicate, e.g. “position changed” or “player died”, it can tell the “Event-Manager”. He will broadcast the event and all subscriber for this event will get notified. This way everything can be interconnected.

Well I guess the introduction above got longer than I was actually planning to, but here we are 🙂 Before we are going to dive deeper into the code, which is C++11 by the way, I will outline the main features of my architecture:

  • memory efficiency – to allow a quick creation and removal of entity, component and system objects as well as events I could not rely on standard new/delete managed heap-memory. The solution for this was of course a custom memory allocator.
  • logging – to see what is going on I used log4cplus[7] for logging.
  • scalable – it is easy to implement new types of entities, components, systems and events without any preset upper limit except your system’s memory
  • flexible – no dependencies exist between entities, components and systems (entities and components sure do have a sort of dependency, but do not contain any pointer logic of each other)
  • simple object lookup/access – easy retrieval of entity objects and there components through an EntityId or a component-iterator to iterate over all components of a certain type
  • flow control – systems have priorities and can depend on each other, therefore a topological order for their execution can be established
  • easy to use – the library can be easily in cooperate into other software; only one include.

The following figure depicts the overall architecture of my Entity-Component-System:

ECS_Overview Figure-01: ECS Architecture Overview (ECS.dll).

As you can see there are four different colored areas in this picture. Each area defines a modular piece of the architecture. At the very bottom – actually in the picture above at the very top; it should be upside down – we got the memory management and the logging stuff (yellow area). This first-tier modules are dealing with very low-level tasks. They are used by the second-tier modules in the Entity-Component-System (blue area) and the event sourcing (red area). These guys mainly deal with object management tasks. Sitting on top is the third-tier module, the ECS_Engine (green area). This high-level global engine object orchestrates all second-tier modules and takes care of the initialization and destruction. All right, this was a short and very abstract overview now let’s get more into the details.

Memory Manager

Let’s start with the Memory-Manager. It’s implementation is based on an article[8] I have found on gamedev.net. The idea is to keep heap-memory allocations and releases to an absolute minimum. Therefore only at application start a big chuck of system-memory is allocated with malloc. This memory now will be managed by one or more custom allocator. There are many types of allocators[9] ( linear, stack, free list…) and each one of them has it’s pro’s and con’s (which I am not going to discuss here). But even if they internally work in a different way they all share a common public interface:

class Allocator
{
     public:
          virtual void* allocate(size_t size) = 0;
          virtual void free(void* p) = 0;
};

The code snippet above is not complete, but outlines the two major public methods each concrete allocator must provide:

  1. allocate – which allocates a certain amount of bytes and returns the memory-address to this chunk and
  2. free – to de-allocates a previously allocated chuck of memory given it’s address.

Now with that said, we can do cool stuff like chaining-up multiple allocators like that:

CustomMemoryMgr Figure-02: Custom allocator managed memory.

As you can see, one allocator can get it’s chunk of memory – that it is going to manage – from another (parent) allocator, which in turn could get it’s memory from another allocator and so on. That way you can establish different memory management strategies. For the implementation of my ECS I provide a root stack-allocator that get’s an initial allocated chuck of 1GB system-memory. Second-tier modules will allocate as much memory as they need from this root allocator and only will free it when the application get’s terminated.

MemoryMgr Figure-03: Possible distribution of global memory.

Figure-03 shows how the global memory could be distributed among the second-tier modules: “Global-Memory-User A” could be the Entity-Manager, “Global-Memory-User B” the Component-Manager and “Global-Memory-User C” the System-Manager.

Logging

I am not going to talk too much about logging as I simply used log4cplus[7] doing this job for me. All I did was defining a Logger base class hosting a log4cplus::Logger object and a few wrapper methods forwarding simple log calls like “LogInfo()”, “LogWarning()”, etc.

Entity-Manager, IEntity, Entity and Co.

Okay now let’s talk about the real meat of my architecture; the blue area in Figure-01. You may have noticed the similar setup between all manager objects and their concerning classes. Have a look at the EntityManager, IEntity and Entity classes for example. The EntityManger class is supposed to manage all entity objects during application run-time. This includes tasks like creating, deleting and accessing existing entity objects. IEntity is an interface class and provides the very basic traits of an entity object, such as an object-identifier and (static-)type-identifier. It’s static because it won’t change after program initialization. This type-identifier is also consistent over multiple application runs and may only change, if source code was modified.

class IEntity
{
    // code not complete!
EntityId m_Id;
 
    public:
        IEntity();
        virtual ~IEntity();
 
        virtual const EntityTypeId GetStaticEntityTypeID() const = 0;
 
        inline const EntityId GetEntityID() const { return this->m_Id; }
};

The type-identifier is an integer value and varies for each concrete entity class. This allows us to check the type of an IEntity object at run-time. Last but not least comes the Entity template class.

template<class T>
class Entity : public IEntity
{
    // code not complete!
 
    void operator delete(void*) = delete;
    void operator delete[](void*) = delete;

public:
 
    static const EntityTypeId STATIC_ENTITY_TYPE_ID;
    
    Entity() {}
    virtual ~Entity() {}
 
    virtual const EntityTypeId GetStaticEntityTypeID() const override { return STATIC_ENTITY_TYPE_ID; }
};
 
// constant initialization of entity type identifier
template<class T>
const EntityTypeId Entity<T>::STATIC_ENTITY_TYPE_ID = util::Internal::FamilyTypeID::Get();

This class’s soul purpose is the initialization of the unique type-identifier of a concrete entity class. I made use of two facts here: first constant initialization[10] of static variables and second the nature of how template classes work. Each Version of the template class Entity will have its own static variable STATIC_ENTITY_TYPE_ID. Which in turn will be guaranteed to be initialized before any dynamic initialization happens. The term “util::Internal::FamilyTypeID::Get()” is used to implement a sort of type counter mechanism. It internally increments a counter every time it gets called with a different T, but always returns the same value when called with the same T again. I am not sure if that patter has a special name, but it is pretty cool 🙂 At this point I also got ride of the delete and delete[] operator. This way I made sure nobody would accidentally call these guys. This also – as long as your compiler is smart enough – would give you a warning when trying to use the new or new[] operator of entity objects as their counterparts are gone. These operators are not intended to be used since the EntityManager class will take care of all this. Alright, let’s summarize what we just learned. The manager class provides basic functionality such as creating, deleting and accessing objects. The interface class functions as the very root base class and provides an unique object-identifier and type-identifier. The template class ensures the correct initialization of the type-identifier and removes the delete/delete[] operator. This very same pattern of a manager, interface and template class is used for components, systems and events as well. The only, but important, thing these groups differ, is the way manger classes store and access their objects.

Let’s have a look at the EntityManager class first. Figure-04 shows the overall structure of how things are stored. 

EntityMgr

Figure-04: Abstract view of EntityManager class and it’s object storage.When creating a new entity object one would use the EntityManager::CreateEntity<T>(args…) method. This public method first takes a template parameter which is the type of the concrete entity to be created. Secondly this method takes in an optional amount of parameters (can be empty) which are forwarded to the constructor of T. Forwarding  these parameters happens through a variadic template[11]. During creation the following things happen internally …

  1. The ObjectPool[12] for entity objects of type T will be acquired, if this pool does not exists a new one will be created
  2. New memory will be allocated from this pool; just enough to store the T object
  3. Before actually calling the constructor of T, a new EntityId is acquired from the manager. This id will be stored along with the before allocated memory into a look-up table, this way we can look-up the entity instance later with that id
  4. Next the C++ in-placement new operator[13] is called with the forwarded args… as input to create a new instance of T
  5. finally the method returns the entity’s identifier.

After a new instance of an entity object got created you can get access to it via it’s unique object identifier (EntityId) and EntityManager::GetEntity(EntityId id). To destroy an instance of an entity object one must call the EntityManager::DestroyEntity(EntityId id) method.

The ComponentManager class works in the same way plus one extension. Besides the object pools for storing all sorts of components it must provide an additional mechanism for linking components to their owning entity objects. This constraint results in a second look-up step: first we check if there is an entry for a given EntityId, if there is one we will check if this entity has a certain type of component attached by looking it up in a component-list.

CompMgr Figure-05: Component-Manager object storage overview.

Using the ComponentManager::CreateComponent(EntityId id, args…) method allows us to add a certain component to an entity. With ComponentManager::GetComponent(EntityId id) we can access the entity’s components, where T specifies what type of component we want to access. If the component is not present nullptr is returned. To remove a component from an entity one would use the ComponentManager::RemoveComponent(EntityId id) method. But wait there is more. Another way of accessing components is using the ComponentIterator. This way you can iterate over all existing components of a certain type T. This might be handy if a system like the “Physics-System” wants to apply gravity to all “Rigidbody-Components”.

The SystemManager class does not have any fancy extras for storing and accessing systems. A simple map is used to store a system along with it’s type-identifier as the key.

The EventManager class uses a linear-allocator that manages a chunk of memory. This memory is used as an event buffer. Events are stored into that buffer and dispatched later. Dispatching the event will clear the buffer so new events can be stored. This happens at least once every frame.

ECS_Access Figure-06: Recap ECS architecture overview

I hope at this point you got a somewhat idea how things work in my ECS. If not, no worries, have a look at Figure-06 and let’s recap. You can see the EntityId is quite important as you will use it to access a concrete entity object instance and all it’s components. All components know their owner, that is, having a component object at hand you can easily get the entity by asking the EntityManager class with the given owner-id of that component. To pass an entity around you would never use it’s pointer directly, but you can use events in combination with the EntityId. You could create a concrete event, let’s say “EntityDied” for example, and this event (which must be a plain old data object) has a member of type EntityId. Now to notify all event listeners (IEventListener) – which could be Entities, Components or Systems – we use EventManager::SendEvent(entityId). The event receiver on the other side now can use the provided EntityId and ask the EntityManager class to get the entity object or the ComponentManager class to get a certain component of that entity. The reason for that detour is simple, at any point while running the application an entity or one of it’s components could be deleted by some logic. Because you won’t clutter your code by extra clean-up stuff you rely on this EntityId. If the manager returns nullptr for that EntityId, you will know that an entity or component does no longer exists. The red square btw. is corresponding to the one in Figure-01 and marks the boundaries of the ECS.

The Engine object

To make things a little bit more comfortable I created an engine object. The engine object ensures an easy integration and usage in client software. On client side one only has to include the “ECS/ECS.h” header and call the ECS::Initialize() method. Now a static global engine object will be initialized (ECS::ECS_Engine) and can be used at client side to get access to all the manager classes. Furthermore it provides  a SendEvent method for broadcasting events and an Update method, which will automatically dispatch all events and update all systems. The ECS::Terminate() should be called before exiting the main program. This will ensure that all acquired resources will be freed. The code snippet bellow demonstrates the very basic usage of the ECS’s global engine object.

#include <ECS/ECS.h>
 
int main(int argc,char* argv[])
{
    // initialize global 'ECS_Engine' object
    ECS::Initialize();
 
    const float DELTA_TIME_STEP = 1.0f / 60.0f; // 60hz
 
    bool bQuit = false;
 
    // run main loop until quit
   while(bQuit == false)
   {
       // Update all Systems, dispatch all buffered events,
       // remove destroyed components and entities ...
       ECS::ECS_Engine->(DELTA_TIME_STEP);
       /*
           ECS::ECS_Engine->GetEntityManager()->...;
           ECS::ECS_Engine->GetComponentManager()->...;
           ECS::ECS_Engine->GetSystemManager()->...;
 
           ECS::ECS_Engine->SendEvent<T>(...);
       */
       // more logic ...
   }
 
   // destroy global 'ECS_Engine' object
   ECS::Terminate();
   return 0;
}

Conclusion

The Entity-Component-System described in this article is fully functional and ready to use. But as usual there are certainly a few thinks to improve. The following list outlines just a few ideas that I came up with:

  • Make it thread-safe,
  • Run each system or a group of systems in threats w.r.t. to their topological order,
  • Refactor event-sourcing and memory management and include them as modules,
  • serialization,
  • profiling

I hope this article was helpful and you enjoyed reading it as much as I did writing it 🙂 If you want to see my ECS in action check out this demo:

The BountyHunter demo makes heavily use of the ECS and demonstrates the strength of this pattern. If you want to know how?, have a look at this post.

So far …

The Entity-Component-System – BountyHunter game (Part 2)

by Tobias Stein on 11/22/17 10:25:00 am

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.


Hey Folks 🙂

Welcome to part two of the series “The Entity-Component-System“. As always you can checkout the original post.

Continuing writing from my last post, where I talked about the Entity-Component-System (ECS) design pattern. I now want to show you how to actually use it to build a game with it. If you not already have seen it, check out what kinda game I built with the help of my ECS.

I will admit this does not look much, but if you ever had build your own game without help of a big and fancy game engine, like Unity or Unreal, you might give me some credit here 😉 So for the purpose of demonstrating my ECS I simply just need that much. If you still have not figured out what this game (BountyHunter) is about, let me help you out with the following picture:

BH_GameRules

The picture on the left may look familiar as it is a more abstract view of the game you saw in the video clip. Focus is laid on game entities. On the right hand side you will find the game objective and rules. This should be pretty much self-explanatory. As you can see we got a bunch of entity types living in this game world and now you may wonder what they are actually made of? Well components of course. While some types of components are common for all this entities a few are unique for others. Check out the next picture.

BH_Comps Figure-02: Entity and their components.

By looking at this picture you can easily see the relation between entities and their components (this is not a complete depiction!). All game entities have the Transform-Component in common. Because game entities must be somewhere located in the world they have a transform, which describes the entities position, rotation and scale. This might be the one and only component attached to an entity. The camera object for instance does require more components especially not a Material-Component as it will be never visible to the player (this might not be true if you would use it for post-effects). The Bounty and Collector entity objects on the other hand do have a visual appearance and therefore need a Material-Component to get displayed. They also can collide with other objects in the game world and therefore have a Collision-Component attached, which describes their physical form. The Bounty entity has one more component attached to it; the Lifetime-Component. This component states the remaining life-time of a Bounty object, when it’s life-time is elapsed the bounty will fade away.

So what’s next? Having all these different entities with their individual gathering of components does not complete the game. We also need someone who knows how to drive each one of them. I am talking about the systems of course. Systems are great. You can use systems to split up your entire game-logic into much smaller pieces. Each piece dealing with a different aspect of the game. There could or actually should be an Input-System, which is handling all the player input. Or a Render-System that brings all the shapes and color onto screen. A Respawn-System to respawn dead game objects. I guess you got the idea. The following picture shows a complete class-diagram of all the concrete entity, component and system types in BountyHunter.

ClassDiagram1 Figure-03: BountyHunter ECS class-diagram.

Now we got entities, components and system (ECS), but wait there is more.. events! To let systems and entities communicate with each other I provided a collection of 38 different events:

GameInitializedEvent GameRestartedEvent GameStartedEvent 
GamePausedEvent GameResumedEvent GameoverEvent GameQuitEvent 
PauseGameEvent ResumeGameEvent RestartGameEvent QuitGameEvent 
LeftButtonDownEvent LeftButtonUpEvent LeftButtonPressedEvent 
RightButtonDownEvent RightButtonUpEvent RightButtonPressedEvent
KeyDownEvent KeyUpEvent KeyPressedEvent ToggleFullscreenEvent
EnterFullscreenModeEvent StashFull EnterWindowModeEvent 
GameObjectCreated GameObjectDestroyed PlayerLeft GameObjectSpawned
GameObjectKilled CameraCreated, CameraDestroyed ToggleDebugDrawEvent
WindowMinimizedEvent WindowRestoredEvent WindowResizedEvent 
PlayerJoined CollisionBeginEvent CollisionEndEvent 

And there is still more , what else did I need to make BountyHunter:

  • general application frameworkSDL2 for getting the player input and setting up the basic application window.
  • graphics – I used a custom OpenGL renderer to make rendering into that application window possible.
  • math – for solid linear algebra I used glm.
  • collision detection – for collision detection I used box2d physics.
  • Finite-State-Machine – used for simple AI and game states.

Obviously I am not going to talk about all these mechanics  as they are worth their own post, which I might do at a later point 😉 But, if your are enthusiastic to get to know anyway I won’t stop you and leave you with this link. Looking at all the features I mentioned above you may realize that they are a good start for your own small game engine. Here are a few more things I got on my todo-list, but actually did not implement just because I wanted to get things done.

  • Editor – an editor managing entities, components, systems and more
  • Savegame – persist entities and their components into a database using some ORM library (e.g. codesynthesis)
  • Replays – recoding events at run-time and replay them at a later point
  • GUI – using a GUI framework (e.g. librocket) to build an interactive game-menu
  • Resource-Manager – synchronous and asynchronous loading of assets (textures, fonts, models etc.) through a custom resource manager
  • Networking – send events across the network and setup a multiplayer mode

I will leave these todo’s up to you as a challenge to proof that you are an awesome programmer 😉

Finally let me provide you some code, which demonstrates the usage of the my ECS. Remember the Bounty game entity? Bounties are the small yellow, big red and all in between squares spawning somewhere randomly in the center of the world. The following snipped shows the code of the class declaration of the Bounty entity.

// Bounty.h
 
class Bounty : public GameObject<Bounty>
{
private:
 
    // cache components
    TransformComponent*   m_ThisTransform;
    RigidbodyComponent*   m_ThisRigidbody;
    CollisionComponent2D* m_ThisCollision;
    MaterialComponent*    m_ThisMaterial;
    LifetimeComponent*    m_ThisLifetime;
 
   // bounty class property
   float                 m_Value;
 
public:
 
    Bounty(GameObjectId spawnId);
    virtual ~Bounty();
 
    virtual void OnEnable() override;
    virtual void OnDisable() override;
 
    inline float GetBounty() const { return this->m_Value; }
 
    // called OnEnable, sets new randomly sampled bounty value
    void ShuffleBounty();
};

The code is pretty much straight forward. I’ve created a new game entity by deriving from GameObject<T> (which is derived from ECS::Entity<T>), with the class (Bounty) itself as T. Now the ECS is aware of that concrete entity type and a unique (static-)type-identifier will be created. We will also get access to the convenient methods AddComponent<U>, GetComponent<U>, RemoveComponent<U>. Besides the components, which I show you in a second, there is another property; the bounty value. I am not sure why I did not put that property into a separate component, for instance a BountyComponent component, because that would be the right way. Instead I just put the bounty value property as member into the Bounty class, shame on me. But hey, this only shows you the great flexibility of this pattern, right? 😉 Right, the components …

// Bounty.cpp
Bounty::Bounty(GameObjectId spawnId)
{
    Shape shape = ShapeGenerator::CreateShape<QuadShape>();
    AddComponent<ShapeComponent>(shape);
    AddComponent<RespawnComponent>(BOUNTY_RESPAWNTIME, spawnId, true);
 
    // cache this components
    this->m_ThisTransform = GetComponent<TransformComponent>();
    this->m_ThisMaterial  = AddComponent<MaterialComponent>(MaterialGenerator::CreateMaterial<defaultmaterial>());
    this->m_ThisRigidbody = AddComponent<RigidbodyComponent>(0.0f, 0.0f, 0.0f, 0.0f, 0.0001f);
    this->m_ThisCollision = AddComponent<CollisionComponent2d>(shape, this->m_ThisTransform->AsTransform()->GetScale(), CollisionCategory::Bounty_Category, CollisionMask::Bounty_Collision);
    this->m_ThisLifetime  = AddComponent<LifetimeComponent>(BOUNTY_MIN_LIFETIME, BOUNTY_MAX_LIFETIME);
}
// other implementations ...

I’ve used the constructor to attach all the components required by the Bounty entity. Note that this approach creates a prefabricate of an object and is not flexible, that is, you will always get a Bounty object with the same components attached to it. Where this is a good enough solution for this game it might be not in a more complex one. In such a case you would provide a factory that produces custom tailored entity objects. As you can see in the code above there are quite a few components attached to the Bounty entity. We got a ShapeComponent and MaterialComponent for the visual appearance. A RigidbodyComponent and CollisionComponent2D for physical behavior and collision response. A RespawnComponent for giving Bounty the ability to get respawned after death. Last but not least there is a LifetimeComponent that will bind the existents of the entity on a certain amount of time. The TransformComponent is automatically attached to any entity that is derived from GameObject<T>. That’s it. We’ve just added a new entity to the game.

Now you probably want to see how to make use of all this components. Let me give you two examples. First the RigidbodyComponent. This component contains information about some physical traits, e.g. friction, density or linear damping. Furthermore it functions as an adapter class which is used to in-cooperate the box2d physics into the game. The RigidbodyComponent is rather important as it is used to synchronize the physics simulated body’s transform (owned by box2d) and the the entities TransformComponent (owned by the game). The PhysicsSystem is responsable for this synchronization process.

// PhysicsEngine.h
 
class PhysicsSystem : public ECS::System<PhysicsSystem>, public b2ContactListener
{
public:
PhysicsSystem();
    virtual ~PhysicsSystem();
 
    virtual void PreUpdate(float dt) override;
    virtual void Update(float dt) override;
    virtual void PostUpdate(float dt) override;
 
    // Hook-in callbacks provided by box2d physics to inform about collisions
    virtual void BeginContact(b2Contact* contact) override;
    virtual void EndContact(b2Contact* contact) override;
}; // class PhysicsSystem
// PhysicsEngine.cpp
 
void PhysicsSystem::PreUpdate(float dt)
{
    // Sync physics rigidbody transformation and TransformComponent
    for (auto RB = ECS::ECS_Engine->GetComponentManager()->begin<RigidbodyComponent>(); RB != ECS::ECS_Engine->GetComponentManager()->end<RigidbodyComponent>(); ++RB)
    {
        if ((RB->m_Box2DBody->IsAwake() == true) && (RB->m_Box2DBody->IsActive() == true))
        {
            TransformComponent* TFC = ECS::ECS_Engine->GetComponentManager()->GetComponent<TransformComponent>(RB->GetOwner());
            const b2Vec2& pos = RB->m_Box2DBody->GetPosition();
            const float rot = RB->m_Box2DBody->GetAngle();
 
            TFC->SetTransform(glm::translate(glm::mat4(1.0f), Position(pos.x, pos.y, 0.0f)) * glm::yawPitchRoll(0.0f, 0.0f, rot) * glm::scale(TFC->AsTransform()->GetScale()));
        }
    }
}
 
// other implementations ...

From the implementation above you may have noticed the three different update functions. When systems get updated, first all PreUpdate methods of all systems are called, then Update and last the PostUpdate methods. Since the PhysicsSystem is called before any other TransformComponent concerned system, the code above ensures a synchronized transform. Here you can also see the ComponentIterator in action. Rather than asking every entity in the world, if it has a RigidbodyComponent, we ask the ComponentManager to give us a ComponentIterator for type RigidbodyComponent. Having the RigidbodyComponent we easily can retrieve the entity’s id and ask the ComponentManager once more to give us the TransformComponent for that id as well, too easy. Let’s check out that second example I’ve promised. The RespawnComponent is used for entities which are intended to be respawned after they died. This component provides five properties which can be used to configure the entity’s respawn behavior. You can decide to automatically respawn an entity when it dies, how much time must pass until it get’s respawned and a spawn location and orientation. The actual respawn logic is implemented in the RespawnSystem.

// RespawnSystem.h
class RespawnSystem : public ECS::System<RespawnSystem>, protected ECS::Event::IEventListener
{
private:
 
    // ... other stuff
    Spawns       m_Spawns;
    RespawnQueue m_RespawnQueue;
 
    // Event callbacks
    void OnGameObjectKilled(const GameObjectKilled* event);
 
public:
 
    RespawnSystem();
    virtual ~RespawnSystem();
 
    virtual void Update(float dt) override;
 
    // more ...
}; // class RespawnSystem
// RespawnSystem.cpp
// note: the following is only pseudo code!
 
voidRespawnSystem::OnGameObjectKilled(const GameObjectKilled * event)
{
    // check if entity has respawn ability
    RespawnComponent* entityRespawnComponent = ECS::ECS_Engine->GetComponentManager()->GetComponent<RespawnComponent>(event->m_EntityID);
 
    if(entityRespawnComponent == nullptr || (entityRespawnComponent->IsActive() == false) || (entityRespawnComponent->m_AutoRespawn == false))
        return;
 
    AddToRespawnQeueue(event->m_EntityID, entityRespawnComponent);
}
 
void RespawnSystem::Update(float dt)
{
    foreach(spawnable in this->m_RespawnQueue)
    {
        spawnable.m_RemainingDeathTime -= dt;
        if(spawnable.m_RemainingDeathTime <= 0.0f)
        {
            DoSpawn(spawnable);
            RemoveFromSpawnQueue(spawnable);
        }
    }
}

The code above is not complete, but grasps the important lines of code. The RespawnSystem is holding and updating a queue of EntityId’s along with their RespawnComponent’s. New entries are enqueued when the systems receives a GameObjectKilled event. The system will check if the killed entity has the respawn ability, that is,  if there is a RespawnComponent attached. If true, then the entity get’s enqueued for respawning, else it is ignored. In the RespawnSystem’s update method, which is called each frame, the system will decrease the initial respawn-time of the queued entitys’ RespawnComponents‘ (not sure if I got the single quotes right here?). If a respawn-time drops below zero, the entity will be respawned and removed from the respawn queue.

I know this was a quick tour, but I hope I could give you a rough idea how things work in the ECS world. Before ending this post I want to share some more of my own experiences with you. Working with my ECS was much a pleasure. It is so surprisingly easy to add new stuff to the game even third-party libraries. I simply added new components and systems, which would link the new feature into my game. I never got the feeling being at a dead end. Having the entire game logic split up into multiple systems is intuitive and comes for free using an ECS. The code looks much cleaner and becomes more maintainable as all this pointer-spaghetti-dependency-confusion is gone. Event sourcing is very powerful and helpful for inter system/entity/… communication, but it is also a double bleeding edge and can cause you some trouble eventually. I am speaking of event raise conditions. If you have ever worked with Unity’s or Unreal Engine’s editor you will be glad to have them. Such editors definitely boost your productivity as your are able to create new ECS objects in much less time than hacking all these line of code by hand. But once you have setup a rich foundation of entity, component, system and event objects it is almost child’s play to plug them together and build something cool out of them. I guess I could go on and talk a while longer about how cool ECS’s are, but I will stop here.

Thanks for swinging by and making it this far 🙂

Cheers, Tobs.

Understanding Component-Entity-Systems
General and Gameplay Programming

Klutzershy

The traditional way to implement game entities was to use object-oriented programming. Each entity was an object, which intuitively allowed for an instantiation system based on classes and enabled entities to extend others through polymorphism. This led to large, rigid class hierarchies. As the number of entities grew, it became increasingly difficult to place a new entity in the hierarchy, especially if the entity needed a lot of different types of functionality. Here, you can see a simple class hierarchy. A static enemy does not fit well into the tree. classdiagram.png To solve this, game programmers started to build entities through composition instead of inheritance. An entity is simply an aggregation (technically a composition) of components. This has some major benefits over the object-oriented architecture described above:

  1. It’s easy to add new, complex entities
  2. It’s easy to define new entities in data
  3. It’s more efficient

Here’s how a few of the entities above would be implemented. Notice that the components are all pure data – no methods. This will be explained in detail below. compositiondiagram.png

The Component

A component can be likened to a C struct. It has no methods and is only capable of storing data, not acting upon it. In a typical implementation, each different component type will derive from an abstract Component class, which provides facilities for getting a component’s type and containing entity at runtime. Each component describes a certain aspect of an entity and its parameters. By themselves, components are practically meaningless, but when used in conjunction with entities and systems, they become extremely powerful. Empty components are useful for tagging entities.

Examples

  • Position (x, y)
  • Velocity (x, y)
  • Physics (body)
  • Sprite (images, animations)
  • Health (value)
  • Character (name, level)
  • Player (empty)

The Entity

An entity is something that exists in your game world. Again, an entity is little more than a list of components. Because they are so simple, most implementations won’t define an entity as a concrete piece of data. Instead, an entity is a unique ID, and all components that make up an entity will be tagged with that ID. The entity is an implicit aggregation of the components tagged with its ID. If you want, you can allow components to be dynamically added to and removed from entities. This allows you to “mutate” entities on the fly. For example, you could have a spell that makes its target freeze. To do this, you could simply remove the Velocity component.

Examples

  • Rock (Position, Sprite)
  • Crate (Position, Sprite, Health)
  • Sign (Position, Sprite, Text)
  • Ball (Position, Velocity, Physics, Sprite)
  • Enemy (Position, Velocity, Sprite, Character, Input, AI)
  • Player (Position, Velocity, Sprite, Character, Input, Player)

The System

Notice that I’ve neglected to mention any form of game logic. This is the job of the systems. A system operates on related groups of components, i.e. components that belong to the same entity. For example, the character movement system might operate on a Position, a Velocity, a Collider, and an Input. Each system will be updated once per frame in a logical order. To make a character jump, first the keyJump field of the Input data is checked. If it is true, the system will look through the contacts contained in the Collider data and check if there is one with the ground. If so, it will set the Velocity‘s y field to make the character jump. Because a system only operates on components if the whole group is present, components implicitly define the behaviour an entity will have. For example, an entity with a Position component but not a Velocity component will be static. Since the Movement system uses a Position and a Velocity, it won’t operate on the Position contained within that entity. Adding a Velocity component will make the Movement system work on that entity, thus making the entity dynamic and affected by gravity. This behaviour can be exploited with “tag components” (explained above) to reuse components in different contexts. For example, the Input component defines generic flags for jumping, moving, and shooting. Adding an empty Player component will tag the entity for the PlayerControl system so that the Input data will be populated based on controller inputs.

Examples

  • Movement (Position, Velocity) – Adds velocity to position
  • Gravity (Velocity) – Accelerates velocity due to gravity
  • Render (Position, Sprite) – Draws sprites
  • PlayerControl (Input, Player) – Sets the player-controlled entity’s input according to a controller
  • BotControl (Input, AI) – Sets a bot-controlled entity’s input according to an AI agent

Conclusion

To wrap up, OOP-based entity hierarchies need to be left behind in favour of Component-Entity-Systems. Entities are your game objects, which are implicitly defined by a collection of components. These components are pure data and are operated on in functional groups by the systems. I hope I’ve managed to help you to understand how Component-Entity-Systems work, and to convince you that they are better than traditional OOP. If you have any questions about the article, I’d appreciate a comment or message. A follow-up article has been posted, which provides a sample C implementation and solves some design problems. Implementing Component-Entity-Systems

Article Update Log

1 April 2013 – Initial submission 2 April 2013 – Initial publication; cleaned up formatting 29 September 2013 – Added notice of follow-up article; changed some formatting)

Implementing Component-Entity-Systems
General and Gameplay Programming

Klutzershy

This is the follow-up to my article from April, Understanding Component-Entity-Systems. If you haven’t read that article yet, I suggest looking it over because it explains the theory behind what I am about to show you. To summarize what was written:

  • Components represent the data a game object can have
  • Entities represent a game object as an aggregation of components
  • Systems provide the logic to operate on components and simulate the game

The purpose of this article is to show how to implement the architecture that I described in an efficient way, and to provide solutions for some sample problems. All the code samples that I provide will be written in C.

Implementation

Components

I wrote in the last article that a component is essentially a C struct: plain old data, so that’s what I used to implement them. They’re pretty self-explanatory. I’ll implement three types of component here:

  1. Displacement (x, y)
  2. Velocity (x, y)
  3. Appearance (name)

Here’s the sample of code defining the Displacement component. It is a simple struct with two members that define its vector components.
typedef struct
{

float x;
float y;
} Displacement;
The Velocity component is defined the same way, and the Appearance has a single string member. In addition to the concrete data types, the implementation makes use of an enum for creating “component masks”, or bit fields, that identify a set of components. Each entity and system has a component mask, the use of which will be explained shortly.
typedef enum
{
COMPONENT_NONE = 0,
COMPONENT_DISPLACEMENT = 1 << 0,
COMPONENT_VELOCITY = 1 << 1,
COMPONENT_APPEARANCE = 1 << 2
} Component;
Defining a component mask is easy. In the context of an entity, a component mask describes which components the entity has. If the entity has a Displacement and a Appearance, the value of its component mask will be COMPONENT_DISPLACEMENT | COMPONENT_APPEARANCE.

Entities

The entity itself will not be defined as a concrete data type. In accordance with data-oriented-design (DOD) principles, having each entity be a structure containing each of its components, creating an “array of structs”, is a no-no. Therefore, each component type will be laid out contiguously in memory, creating a “struct of arrays”. This will improve cache coherency and facilitate iteration. In order to do this, the entity will be represented by an index into each component array. The component found at that index is considered as part of that entity. I call this “struct of arrays” the World. Along with the components themselves, it stores a component mask for each entity.
typedef struct
{

int mask[ENTITY_COUNT];

Displacement displacement[ENTITY_COUNT];
Velocity velocity[ENTITY_COUNT];
Appearance appearance[ENTITY_COUNT];
} World;
ENTITY_COUNT is defined in my test program to be 100, but in a real game it will likely be much higher. In this implementation, the maximum number of entities is constrained to this value. I prefer to use stack-allocated memory to dynamic memory, but the world could also be implemented as a number of C++-style vectors, one per component. Along with this structure, I have defined a couple of functions that are able to create and destroy specific entities.
unsigned int createEntity(World *world)
{
unsigned int entity;
for(entity = 0; entity < ENTITY_COUNT; ++entity)
{
if(world->mask[entity] == COMPONENT_NONE)
{
return(entity);
}
}

printf(“Error! No more entities left!\n”);
return(ENTITY_COUNT);
}

void destroyEntity(World *world, unsigned int entity)
{
world->mask[entity] = COMPONENT_NONE;
}
The first does not “create” an entity per se, but instead returns the first “empty” entity index, i.e. for the first entity with no components. The second simply sets an entity’s component mask to nothing. Treating an entity with an empty component mask as “non-existent” is very intuitive, because no systems will run on it. I’ve also created a few helper functions to create a fully-formed entity from initial parameters such as displacement and velocity. Here is the one that creates a tree, which has a Displacement and an Appearance.
unsigned int createTree(World *world, float x, float y)
{
unsigned int entity = createEntity(world);

world->mask[entity] = COMPONENT_DISPLACEMENT | COMPONENT_APPEARANCE;

world->displacement[entity].x = x;
world->displacement[entity].y = y;

world->appearance[entity].name = “Tree”;

return(entity);
}
In a real-world engine, your entities would likely be defined using external data files, but that is beyond the scope of my test program. Even so, it is easy to see how flexible the entity creation system is.

Systems

The systems are easily the most complex part of the implementation. Each system is a generic function which is mapped to a certain component mask. This is the second use of a component mask: to define which components a certain system operates on.
#define MOVEMENT_MASK (COMPONENT_DISPLACEMENT | COMPONENT_VELOCITY)

void movementFunction(World *world)
{
unsigned int entity;
Displacement *d;
Velocity *v;

for(entity = 0; entity < ENTITY_COUNT; ++entity)
{
if((world->mask[entity] & MOVEMENT_MASK) == MOVEMENT_MASK)
{
d = &(world->displacement[entity]);
v = &(world->velocity[entity]);

v->y -= 0.98f;

d->x += v->x;
d->y += v->y;
}
}
}
Here is where the component mask becomes really powerful. It makes it trivial to select an entity based on whether or not it has certain components, and it does it quickly. If each entity was a concrete structure with a dictionary or set to show which components it has, it would be a much slower operation. The system itself adds the effect of gravity and then moves any entity with both a Displacement and a Velocity. If all entities are initialized properly, every entity processed by this function is guaranteed to have a valid Displacement and Velocity. The one downside of the component mask is that the number of possible components is finite. In this implementation it is 32 because the default integer type is 32 bits long. C++ provides the std::bitset class, which is N bits long, and I’m sure other languages provide similar facilities. In C, the number of bits can be extended by using multiple component masks in an array and checking each one independently, like this:
(EntityMask[0] & SystemMask[0]) == SystemMask[0] && (EntityMask[1] & SystemMask[1]) == SystemMask[1] // && ...

Source Files

I’ve zipped up the source code here. Main.c runs a sample program that creates three entities and runs each system once. CES.zip

Real-World Problems

This implementation works very well in the small scope of my program and can easily be extended to use more components and systems. It can also easily be extended to run in a main loop, and extended to read entities from data files with some work. This section will tackle some problems with transferring gameplay mechanics and advanced features over to my implementation of CES.

Power-ups and collision filtering

This problem was pitched to me by Krohm in a comment on the original article. He was asking about gameplay-specific behaviours in general, but provided the specific example of a power-up that stopped collisions with a certain entity type. Dynamic components to the rescue! Let’s create a component, say GhostBehaviour, that has a list of qualifiers for determining which entities an object can pass through. For example, a list of component masks, or possibly material indices. Any component can be added or removed (technically, enabled or disabled) from any entity at any time, simply by changing that entity’s component mask. When the player grabs the powerup, the GhostBehaviour component will be added. It could also have a built-in timer to automatically remove itself after a few seconds. To actually disable the necessary collisions, the typical collision response in a physics engine can be exploited. In most physics engines, there is first a step to detect collisions and produce contacts, and then a step to actually apply the contact forces to each body. Let’s say that each of those steps is implemented in a system, and that there is a component that keeps track of each entity’s collision contacts (Collidable). To permit the desired behaviour, each contact should store the index of the other entity. By injecting a system that operates on a GhostBehaviour and a Collidable in between the two physics steps, the contacts between the entities that should pass through each other can be deleted before they are acted upon by the physics engine. This will have the effect of a disabled collision. The same system can also disable the GhostBehaviour after a few seconds. A similar approach can be used to perform a certain action upon collision. There could be a unique system for every action, or the same system could govern all the actions. In any case, the system would read the collision contacts to determine whether the entity collided with some other entity and then act accordingly. In fact, this would be needed to give the player the power-up in the first place.

The Big F***ing Spell – Destroying all monsters

Another problem I received was how to kill all monsters with a spell. Thanks to smorgasbord for this one! The key to solving this one is that a system can be run somewhere outside of the top-level main loop, and that any entity that is a monster, according to CES rules, satisfies the same component mask. For example, every entity with both Health and AI is a monster, and this can be described with a component mask. Remember how a system is just a function and a component mask? Let’s define the “kill all monsters” spell as a system. The function, at its core, is destroyEntity, but could also create particle effects or play a sound. The component mask of the system can be COMPONENT_HEALTH | COMPONENT_AI. In terms of actually casting the spell, I mentioned in the previous article that each entity can have one or more input components, which store boolean or real values that map to various inputs, including AI and networked players. Let’s create a MagicInputComponent that has a boolean value that says when the entity should cast the spell, and an ID corresponding to the spell that should be cast. Each spell has a unique ID, which is actually a key in a lookup table. This lookup table maps a spell ID to the function that “casts” that spell. In this case, the function would run the system..

Conclusion

Remember that this is just a sample implementation. It works for the test program, but is probably not ready for a full game. However, I hope that the design principles have been made clear and that it is easy to understand and implement in your own way in a different language. If you have any more problems you’d like me to solve you can write a comment or send me a message. I’ll update this article periodically with my solutions. Keep in touch for the next article!

Article Update Log

29 September 2013 – Initial submission 2 October 2013 – Initial publication; simplified system code (thanks TiagoCosta!); clarified 2nd example (thanks BeerNutts!)] 21 October 2013 – Reflected code changes in the source archive

Nomad Game Engine: Part 2 — ECS

Down with inheritance!

This post is part of a series where I’m documenting my experience building an ECS game engine from scratch. Check out the homepage for this project for more posts, information, and source code.

Entity Component System

As mentioned in my last post, the game engine I’m starting to make is going to follow ECS (Entity Component System) methodology. In this blog post I’m going to do my best to explain my implementation of ECS as simply as possible. There are many great resources that have been created by people much smarter than me explaining ECS, so you might be wondering why I’m even bothering to make a post about this.

  1. If I’m going to make a blog series about this engine, I think it’s better to have a holistic approach than to just link to a bunch of other people’s posts about a topic.
  2. There are actually many different ways to implement an ECS engine that vary quite dramatically. By making this post I’m setting ground work for the posts to come.

Entities and Components

ECS follows the principle of composition over inheritance. The following examples should be able to illustrate this concept, but if you’re curious about it, I’d highly recommend checking out this video, as it does a great job of explaining why composition over inheritance is important.

In Nomad, we have Entities, Components, and Systems (ECS). To explain these concepts, I’m going to use this example:

Three entities

In this example, we have three entities, or game objects — the player, the log, and the orb. Here are the game’s requirements:

  1. The player is controlled by the arrow keys
  2. The player and the orb both have a health value (can take damage)
  3. The player can’t walk through the log (but the orb can float over it)

In an ECS architecture, entities are assigned components based on what attributes they have. We can drill down into the requirements above to find that we have 7 basic components:

Our 7 components

This might seem like a lot of components that make the game unnecessarily complex, but we can see that each of the components is actually a very small piece of functionality, which makes it much easier to conceptualize. With these components, let’s take a look at our entities:

Entities and their components

This is the essence of ECS: an entity is simply a collection of components which provide functionality. When done properly, components can be added and removed to add or remove functionality. For example, if I wanted the orb to collide with the log and player as well, I could simply add a “Collision” component to it. If the player had an invisibility cloak, I could simply remove its “Sprite” component. Intuitive, right?

Changing how the game works is as easy as adding or removing a component!

ECS with a data-driven approach

Okay, so we’ve got a bunch of entities that have components assigned to them. How does this actually work behind the scenes? This is where Nomad gets slightly more complex. Let’s take a look at what Nomad thinks an entity is:

struct Entity {
    unsigned int id;
}

Yup, that’s right. It’s just an id. That means no functionality, no implementation. Just data. How about taking a look at one of our components:

struct HealthComponent {
    int currentHealth;
    int maxHealth;
}

Once again, no functionality, just data. With this new knowledge, I should clarify our components:

Data oriented components

You’ll notice that now no functionality is assumed by any of these components, they’re simply bags of data.

So at this point you probably have two main questions:

  1. How are Entities and Components tied together?
  2. Where is the actual code (functionality)?

Component Managers

The answer to the first question is actually very simple. Component managers manage all components of one type and keep references to which entities own them. Here’s how the data is actually organized in Nomad:

Component Managers hold all the components (the number below each component is the entity associated with it)

Giving components their own managers as opposed to letting entities own components may seem to be an arbitrary decision, but doing so actually gives a serious performance increase. For a moment, let’s dive into the memory layout of both of these options:

Memory layout for our two possibilities

The most important information to know here is that processors love to iterate over arrays of contiguous data. The less we jump around the computer’s memory, the better.

Let’s use an example to show why the right side is much better performance-wise. Our player (and his trusty companion the orb) are fighting a boss who decides to throw a bomb that reduces everyone in the area’s health by 20% for the duration of the fight.

The bomb reduces maximum health by 20%

The pseudocode would look like this:

foreach(entity hit by bomb):
    HealthComponent hp = entity.getHealth();
    hp.maxHealth = hp.maxHealth * 0.8;
Memory accesses for updating a single component

If our entities held their own components, we would be jumping in memory from the “player” entity’s memory to the “orb” entity’s memory. In this loop, we are sequentially accessing random memory locations, which is not ideal. However, if we hold components contiguously in memory, we’re accessing an array of data in order, which processors love. Obviously, this example is only two components, but for the sake of argument let’s consider that a game might have hundreds of components of a given type. The performance difference between jumping around in memory to update their maximum health and simply running through an array is sizable.

Systems

Alright, so we’ve covered Entities and Components in reasonable depth. How do we actually add functionality? Where does the game code go?

The answer to that is “systems”. Entities and components are just data containers, and systems are the ones who actually modify that data. In Nomad, a system can specify a set of component types that it wishes to pay attention to. Any component that has the necessary components will be updated by the system. This might sound confusing, but it should make more sense after an example.

Movement System

The movement system is one of the most basic and necessary systems. If you take a look at the components we listed up above, you’ll notice that we had both a Transform and a Motion component. Here’s what they look like (note that in the game code they look a bit different but this should serve to illustrate the concept):

struct Transform {
    int x;
    int y;
}
struct Motion {
    Vec2 velocity;
    Vec2 acceleration;
}

The movement system is in charge of updating all entities’ positions and velocities every game tick. Therefore, the movement system states that it wants to pay attention to any entities that have both a “Transform” and a “Motion” component. As components are added and removed, the list of entities that the movement system pays attention to will change. Every update, the movement system will run something like this:

void update(int dt){
    for(entity in m_entities){
        TransformComponent position = entity.getTransform();
        MotionComponent motion = entity.getMotion();
        position.x += motion.velocity.x;
        position.y += motion.velocity.y;
        motion.velocity.x += motion.acceleration.x;
        motion.velocity.y += motion.acceleration.y;
    }
}

Once again let’s think of how memory is traversed in this update() function.

Movement System memory accesses

Notice a couple important things about this chart:

  1. We’re not actually accessing every “transform” component. This is because Entity #2 (The log) doesn’t have a motion component, so the Movement system doesn’t pay attention to it.
  2. Even though we’re skipping the 2nd “transform” component, our memory accesses are still using an array of data, which gives us great performance increases. As we add more entities that move, the performance gains continue to increase.

Back to our example

Let’s take a look at the systems we would need to bring our original example to life (once again, remember that a system will only pay attention to an entity that has *all* of the required components):

The systems we would need to create our game.

Based on these systems, we can see that the player entity would be part of Movement, Player Input, Collision, and Render. The log entity would be part of the Collision system and the Render system, and the orb entity would be part of the Movement, Follow, and Render systems. Note for the astute among you that collision system would normally need to take motion into account as well, but we’re leaving it out for this example.

Adding a new feature or functionality is simple, simply add components and systems as needed. Because systems are independent and only deal with a specific subset of components, the game engine has very low coupling, which makes it a lot easier to debug and plan. In addition, the majority of systems don’t actually need to be run in a certain order, so we can have different systems execute on different threads concurrently, significantly boosting our performance.

Here are a couple other implementations that might differ slightly from mine but do a good job of explaining ECS:

Current Progress

Current progress of Nomad.

Most of the boxes you see are for debugging (bounding boxes for collisions, etc.). A couple changes since my last post:

  • Collision detection now uses spatial hashing (the black squares)
  • Sprites are now drawn in z-order (that’s why the player can run both behind and in front of the tree)
  • Added the ability to sword slash
  • Added rotation to the Transform component (both fireball and sword slash use it)

Keep your eye out in the next couple weeks for my next post in the series!

Component Based Engine Design

What is Component Based Design?

Component based engine design was originally pioneered in order to avoid annoying class hierarchies that inheritance introduces. The idea is to package all functionality of game objects into separate objects. A single game object is just a collection of the components, as so the components of a game object define it’s behavior, appearance and functionality. This is perfectly fine, though there are plenty of resources out that talk about this topic. However I’d like to take a step back and start from the top.

It should be noted that the implementation presented here is just one way of going about things, and comes directly from my highly subjective opinion. Perhaps you as a reader can come up with or know of better solutions or designs.

Here is an example game object, note that the game object is generic and simply contains some components:


The Actual Engine

The engine of a game can be thought of as a manager of systems. As to what a system is, we’ll get to that later, for now think of a system as either Physics, Graphics or AI. The engine ought to have a main loop function, as well as an update function. The update function calls update on all contained systems in a specific order. The main loop function is just a small infinite loop that calls update.

Often times the main loop will deal with timestepping itself. Have a look at the linked article to learn more about proper timestepping.

It is important to have your engine expose the update function, as sometimes your engine will need to be compiled as a static library and linked to externally. In this case the main loop of your simulation may reside outside of the engine library altogether. A common usage I’ve seen for this sort of design choice is when creating an editor of some sort, perhaps a level or content editor. Often times these editors will have a veiwport to preview the game, and in order to do so access to some sort of engine update function is necessary.

Beyond containing and calling update, the Engine also forwards global messages to all the systems. More on messaging later.


Singletons?

Creating more than one instance of an engine should never happen. The question of “should I make this a singleton” will sometimes arise. In my experience the answer is often no. Unless you’re working on a large team of programmers where the chances of some moron making an instance of some Engine or System class, making things a singleton is just a waste of time. Especially if retrieving data from that singleton incurs a little bit of overhead.


Systems

Each system in the engine corresponds to one type of functionality. This idea is best shown by example, so here are the various systems I usually have in engines I work on:

  • Graphics
  • Physics
  • GameLogic
  • Windowing/Input
  • UI
  • Audio
  • ObjectFactory – Creates objects and components from string or integral ID

Each system’s primary functionality is to operate upon game objects. You can think of a system as a transform function: data is input, modified somehow, and then data is output. The data passed to each system should be a list of game objects (or of components). However a system only updates components on game objects, and the components to be updated are the ones related to that system. For example the graphics system would only update sprite or graphics related components.

Here’s an example header file for a system:

The naive approach to a system update would be to pass a list of game objects like so:

The above code is assuming the ObjectFactory contains all game objects, and can be accessed somehow (perhaps by pointer). This code will work, and it’s exactly what I started with when I wrote my first engine. However you’ll soon realize the folly involved here.


Cache is King

That’s right, those who have the gold makes the rules; the golden rule. In a more serious sense, cache is king due to processing speed related to memory access speed. The bottleneck in all engines I have ever seen or touched in the past couple years has been due to poor memory access patterns. Not a single serious bottleneck was due computation.

Currently modern hardware performs very very fast. Reaching for data in memory (RAM, not just hard disk) is orders of magnitude slower. So caches come the rescue. A cache can be thought of, in a simplified sense, as a small chunk of memory right next to the CPU (or GPU). Accessing the cache memory is way faster than going all the way out to main RAM. Whenever memory is fetched from RAM memory around that RAM location is also placed into the CPU cache. The idea here is that when you retrieve something from RAM the likelyhood of requiring to fetch something very nearby is high, so all the data in that area is grabbed all at once.

Long story short, if you place things that need to be accessed at around the same time next to each other in memory, huge performance benefits will be reaped. The best performance comes from traversing memory linearly, as if iterating over an array. This means that if we can stick things into arrays and traverse these arrays linearly, there will be no faster form of memory access.

Fetching memory that does not exist in the cache is called a cache miss.


Cache and Components

Lets revisit the naive approach to updating systems. Assuming a system is handed a generic game object, that system must then retrieve its corresponding component(s) to update, like so:

As this loop is run the memory of every game object and every component type that corresponds to the system is touched. A cache miss will likely be incurred over and over as the loop runs bouncing around in memory. This is even worse if the ObjectFactory is just creating random objects with new, as every memory access to every object and every component will likely incur cache misses.

What do? The solution to all these memory access problems is to simplify the data into arrays.


Arrays GameObjects + Components

I suggest having every game object exist within a single giant array. This array should probably be contained within the ObjectFactory. Usage of std::vector for such a task is recommended. This keeps game objects together in memory, and even though deletion of a game object is of O(n) complexity, that O(n) operation traverses an array, and usually will turn out to be unnoticeable. A custom vector or array class can be created that avoids the O(n) operation entirely by taking the element at the end, and placing it into the deleted slot. This can only be done if references into the array are translated handles (more on handles momentarily).

Every component type should be in a giant array too. Each component array should be stored within their respective systems (but can be “created” from the Factory). Again, an array like data structure would be ideal.

This simple setup allows for linear traversal of most memory in the entire engine, so long as the update function of each system is redesigned slightly. Instead of handing a list of game objects to each system, the system can just iterate over its related components directly, since the components are stored within the systems already.


So, how are Game Objects “handled” now?

Since components have been moved into large arrays, and the game objects themselves are in a big array, what exactly should the relationship between a game object and a component be? In the naive implementation some sort of map would have worked perfectly fine, as the memory location of each component could be anywhere due to the use of new calls. However the relation isn’t so carefree.

Since things are stored in arrays its time to switch from pointer-centric relationships to handle based relationships. A handle can be thought of in its simplest form an index into an array. Since game objects and components are stored in arrays, it is only natural that to access a game object you do so by index. This allows for these giant arrays to grow and shrink as necessary without obliterating dangling pointers in the rest of the program.

Here’s a code example:

As you can see, an array of handles is stored to represent the containment of components. There is one slot in the array for each type of component. By design this limits each component to be of unique type within a game object. Each handle is an index into a large array of components. This index is used to retrieve components that correspond to a game object. A special value (perhaps -1, or by some other mechanism) can be used to denote “no component”.

Handles can get quite a bit more versatile than just a plain ol’ integer. I myself created a HandleManager for translating an integer into a pointer. Here’s a great resource for creating your own handle manager.

The idea of translating a handle into a pointer is such that once the pointer is used it is not kept around. Just let it be reclaimed back into the stack. This makes it so that every time a pointer is required there is a translation of handle to a single pointer somewhere in memory. This constant translation allows for the actual pointer value to be translated to, to be swapped for another pointer at any time without fear of leaving dangling pointers.


Where does the Code go?

Code for update routines can be put into either systems or components. The choice is yours entirely. A more data oriented approach would put as much code into systems as possible, and just use components as buckets of data. I myself prefer this approach. However once you hit game logic components virtual functionality is likely to be desired, and so code will likely be attached directly to such components.

The last engine I built used the naive approach to component based design, and it worked wonderfully. I used a block allocator so cache misses weren’t as high as with raw new calls.

The point is, do what makes most sense and keep things simple. If you want to store routines within your components and use virtual function calls, then you’ll probably have trouble storing things in an array unless you place all memory in the base class. If you can externalize as much code from your components as possible, it may be simpler to keep all your components in an array.

There is a tradeoff between flexibility and efficiency. My personal preference is to store performance sensitive components in huge arrays, and keep AI and game logic related things together in memory as much as possible, but not really stress too much about it. Game logic and AI should probably just be rather flexible, and so details about memory locations aren’t so important. One might just allocate these types of components with a block allocator and call it good.


Messaging

The last major devil in an engine is messaging. Messaging is transferring data from one location to another. In this sense the most basic form of messaging is a simple function call.

Taking this a step further, we’d like to be able to send messages over a connection in a generic manner. It should not matter what type of message we send; all messages should be sent the same way to reduce code duplication and complexity. The most basic form of this is dynamic dispatch, or virtual function calls. An ID is introduced to the message so the internal data can be typecasted to the correct type.

Still, we can do better. Lets imagine we have a sort of GameLogic component or system. We need a way to send a message to this object that contains some data. Lets not focus much on memory access patterns, as simplicity and flexibility are key here. Take a look at this code:

This code highlights the usage of messaging quite well. Say the player emits some messages as it walks around, perhaps something like “I’m here” to all nearby things in a level. The player can blindly send these messages across the SendMessage function without caring about whether or not it will respond or do anything. As you can see, the implementation of the SendMessage function ignores most message types and responds to a few.

In this example when the player nears the treasure chest it will glimmer a bit. Perhaps when the player gets closer it glimmers brighter and brighter. In order to do so, the MSG object sent to the treasure chest ought to contain the player coordinates, and so it can be typecasted to the appropriate message type.

The eActivate message may be emitted by the player whenever they hit the “e” button. Anything that could possibly respond to an eActive message will do so, and the rest of the objects receiving the message will safely ignore it.

This type of messaging is simple and easy to implement, quite efficient (if a block allocator or stack memory is used for the messages), and rather powerful.

A more advanced version of messaging makes heavy use of C++ introspection. A future article will likely be devoted to this topic, as it’s a hefty topic altogether. Edit: Here’s a link to a slideshow I presented at my university.


Conclusion and Resources

This was a rather whirlwind tour through a lot of different information -I hope it all came out coherent. Please don’t hesitate to ask any questions or add comments; I may even just update this post with more information or clarifications!

What is an Entity Component System architecture for game development?

Posted on

Last week I released Ash, an entity component system framework for Actionscript game development, and a number of people have asked me the question “What is an entity component system framework?”. This is my rather long answer.

Entity systems are growing in popularity, with well-known examples like Unity, and lesser known frameworks like Actionscript frameworks Ember2, Xember and my own Ash. There’s a very good reason for this; they simplify game architecture, encourage clean separation of responsibilities in your code, and are fun to use.

In this post I will walk you through how an entity based architecture evolves from the old fashioned game loop. This may take a while. The examples will be in Actionscript because that happens to be what I’m using at the moment, but the architecture applies to all programming language.

Note that the naming of things within this post is based on

  • How they were named as I discovered these archtectures over the past twenty years of my game development life
  • How they are usually named in modern entity component system architectures

This is different, for example, to how they are named in Unity, which is an entity architecture but is not an entity component system architecture.

This is based on a presentation I gave at try{harder} in 2011.

The examples

Throughout this post, I’ll be using a simple Asteroids game as an example. I like to use Asteroids as an example because it involves simplified versions of many of the systems required in larger games – rendering, physics, ai, user control of a character, non-player characters.

The game loop

To understand why we use entity systems, you really need to understand the old-fashioned game loop. A game loop for Asteroids might look something like this

function update( time:Number ):void
{
  game.update( time );
  spaceship.updateInputs( time );
  for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
  {
    flyingSaucer.updateAI( time );
  }
  spaceship.update( time );
  for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
  {
    flyingSaucer.update( time );
  }
  for each( var asteroid:Asteroid in asteroids )
  {
    asteroid.update( time );
  }
  for each( var bullet:Bullet in bullets )
  {
    bullet.update( time );
  }
  collisionManager.update( time );
  spaceship.render();
  for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
  {
    flyingSaucer.render();
  }
  for each( var asteroid:Asteroid in asteroids )
  {
    asteroid.render();
  }
  for each( var bullet:Bullet in bullets )
  {
    bullet.render();
  }
}

This game loop is called on a regular interval, usually every 60th of a second or every 30th of a second, to update the game. The order of operations in the loop is important as we update various game objects, check for collisions between them, and then draw them all. Every frame.

This is a very simple game loop. It’s simple because

  1. The game is simple
  2. The game has only one state

In the past, I have worked on console games where the game loop, a single function, was over 3,000 lines of code. It wasn’t pretty, and it wasn’t clever. That’s the way games were built and we had to live with it.

Entity system architecture derives from an attempt to resolve the problems with the game loop. It addresses the game loop as the core of the game, and pre-supposes that simplifying the game loop is more important than anything else in modern game architecture. More important than separation of the view from the controller, for example.

Processes

The first step in this evolution is to think about objects called processes. These are objects that can be initialised, updated on a regular basis, and destroyed. The interface for a process looks something like this.

interface IProcess
{
  function start():Boolean;
  function update( time:Number ):void;
  function end():void;
}

We can simplify our game loop if we break it into a number of processes to handle, for example, rendering, movement, collision resolution. To manage those processes we create a process manager.

class ProcessManager
{
  private var processes:PrioritisedList;

  public function addProcess( process:IProcess, priority:int ):Boolean
  {
    if( process.start() )
    {
      processes.add( process, priority );
      return true;
    }
    return false;
  }

  public function update( time:Number ):void
  {
    for each( var process:IProcess in processes )
    {
      process.update( time );
    }
  }

  public function removeProcess( process:IProcess ):void
  {
    process.end();
    processes.remove( process );
  }
}

This is a somewhat simplified version of a process manager. In particular, we should ensure we update the processes in the correct order (identified by the priority parameter in the add method) and we should handle the situation where a process is removed during the update loop. But you get the idea. If our game loop is broken into multiple processes, then the update method of our process manager is our new game loop and the processes become the core of the game.

The render process

Lets look at the render process as an example. We could just pull the render code out of the original game loop and place it in a process, giving us something like this

class RenderProcess implements IProcess
{
  public function start() : Boolean
  {
    // initialise render system
    return true;
  }

  public function update( time:Number ):void
  {
    spaceship.render();
    for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
    {
      flyingSaucer.render();
    }
    for each( var asteroid:Asteroid in asteroids )
    {
      asteroid.render();
    }
    for each( var bullet:Bullet in bullets )
    {
      bullet.render();
    }
  }
  
  public function end() : void
  {
    // clean-up render system
  }
}

Using an interface

But this isn’t very efficient. We still have to manually render all the different types of game object. If we have a common interface for all renderable objects, we can simplify matters a lot.

interface IRenderable
{
  function render();
}
class RenderProcess implements IProcess
{
  private var targets:Vector.<IRenderable>;

  public function start() : Boolean
  {
    // initialise render system
    return true;
  }

  public function update( time:Number ):void
  {
    for each( var target:IRenderable in targets )
    {
      target.render();
    }
  }
  
  public function end() : void
  {
    // clean-up render system
  }
}

Then our spaceship class might contain some code like this

class Spaceship implements IRenderable
{
  public var view:DisplayObject;
  public var position:Point;
  public var rotation:Number;

  public function render():void
  {
    view.x = position.x;
    view.y = position.y;
    view.rotation = rotation;
  }
}

This code is based on the flash display list. If we were blitting, or using stage3d, it would be different, but the principles would be the same. We need the image to be rendered, and the position and rotation for rendering it. And the render function does the rendering.

Using a base class and inheritance

In fact, there’s nothing in this code that makes it unique to a spaceship. All the code could be shared by all renderable objects. The only thing that makes them different is which display object is assigned to the view property, and what the position and rotation are. So lets wrap this in a base class and use inheritance.

class Renderable implements IRenderable
{
  public var view:DisplayObject;
  public var position:Point;
  public var rotation:Number;

  public function render():void
  {
    view.x = position.x;
    view.y = position.y;
    view.rotation = rotation;
  }
}
class Spaceship extends Renderable
{
}

Of course, all renderable items will extend the renderable class, so we get a simple class heirarchy like this

The move process

To understand the next step, we first need to look at another process and the class it works on. So lets try the move process, which updates the position of the objects.

interface IMoveable
{
  function move( time:Number );
}
class MoveProcess implements IProcess
{
  private var targets:Vector.<IMoveable>;
  
  public function start():Boolean
  {
    return true;
  }

  public function update( time:Number ):void
  {
    for each( var target:IMoveable in targets )
    {
      target.move( time );
    }
  }
  
  public function end():void
  {
  }
}
class Moveable implements IMoveable
{
  public var position:Point;
  public var rotation:Number;
  public var velocity:Point;
  public var angularVelocity:Number;

  public function move( time:Number ):void
  {
    position.x += velocity.x * time;
    position.y += velocity.y * time;
    rotation += angularVelocity * time;
  }
}
class Spaceship extends Moveable
{
}

Multiple inheritance

That’s almost good, but unfortunately we want our spaceship to be both moveable and renderable, and many modern programming languages don’t allow multiple inheritance.

Even in those languages that do permit multiple inheritance, we have the problem that the position and rotation in the Moveable class should be the same as the position and rotation in the Renderable class.

One common solution is to use an inheritance chain, so that Moveable extends Renderable.

class Moveable extends Renderable implements IMoveable
{
  public var velocity:Point;
  public var angularVelocity:Number;

  public function move( time:Number ):void
  {
    position.x += velocity.x * time;
    position.y += velocity.y * time;
    rotation += angularVelocity * time;
  }
}
class Spaceship extends Moveable
{
}

Now the spaceship is both moveable and renderable. We can apply the same principles to the other game objects to get this class hierarchy.

We can even have static objects that just extend Renderable.

Moveable but not Renderable

But what if we want a Moveable object that isn’t Renderable? An invisible game object, for example? Now our class hierarchy breaks down and we need an alternative implementation of the Moveable interface that doesn’t extend Renderable.

class InvisibleMoveable implements IMoveable
{
  public var position:Point;
  public var rotation:Number;
  public var velocity:Point;
  public var angularVelocity:Number;

  public function move( time:Number ):void
  {
    position.x += velocity.x * time;
    position.y += velocity.y * time;
    rotation += angularVelocity * time;
  }
}

In a simple game, this is clumsy but manageable, but in a complex game using inheritance to apply the processes to objects rapidly becomes unmanageable as you’ll soon discover items in your game that don’t fit into a simple linear inheritance tree, as with the force-field above.

Favour composition over inheritance

It’s long been a sound principle of object-oriented programming to favour composition over inheritance. Applying that principle here can rescue us from this potential inheritance mess.

We’ll still need Renderable and Moveable classes, but rather than extending these classes to create the spaceship class, we will create a spaceship class that contains an instance of each of these classes.

class Renderable implements IRenderable
{
  public var view:DisplayObject;
  public var position:Point;
  public var rotation:Number;

  public function render():void
  {
    view.x = position.x;
    view.y = position.y;
    view.rotation = rotation;
  }
}
class Moveable implements IMoveable
{
  public var position:Point;
  public var rotation:Number;
  public var velocity:Point;
  public var angularVelocity:Number;

  public function move( time:Number ):void
  {
    position.x += velocity.x * time;
    position.y += velocity.y * time;
    rotation += angularVelocity * time;
  }
}
class Spaceship
{
  public var renderData:IRenderable;
  public var moveData:IMoveable;
}

This way, we can combine the various behaviours in any way we like without running into inheritance problems.

The objects made by this composition, the Static Object, Spaceship, Flying Saucer, Asteroid, Bullet and Force Field, are collectively called entities.

Our processes remain unchanged.

interface IRenderable
{
  function render();
}
class RenderProcess implements IProcess
{
  private var targets:Vector.<IRenderable>;

  public function update(time:Number):void
  {
    for each(var target:IRenderable in targets)
    {
      target.render();
    }
  }
}
interface IMoveable
{
  function move();
}
class MoveProcess implements IProcess
{
  private var targets:Vector.<IMoveable>;

  public function update(time:Number):void
  {
    for each(var target:IMoveable in targets)
    {
      target.move( time );
    }
  }
}

But we don’t add the spaceship entity to each process, we add it’s components. So when we create the spaceship we do something like this

public function createSpaceship():Spaceship
{
  var spaceship:Spaceship = new Spaceship();
  ...
  renderProcess.addItem( spaceship.renderData );
  moveProcess.addItem( spaceship.moveData );
  ...
  return spaceship;
}

This approach looks good. It gives us the freedom to mix and match process support between different game objects without getting into spagetti inheritance chains or repeating ourselves. But there’s one problem.

What about the shared data?

The position and rotation properties in the Renderable class instance need to have the same values as the position and rotation properties in the Moveable class instance, since the Move process will change the values in the Moveable instance and the Render process will use the values in the Renderable instance.

class Renderable implements IRenderable
{
  public var view:DisplayObject;
  public var position:Point;
  public var rotation:Number;

  public function render():void
  {
    view.x = position.x;
    view.y = position.y;
    view.rotation = rotation;
  }
}
class Moveable implements IMoveable
{
  public var position:Point;
  public var rotation:Number;
  public var velocity:Point;
  public var angularVelocity:Number;

  public function move( time:Number ):void
  {
    position.x += velocity.x * time;
    position.y += velocity.y * time;
    rotation += angularVelocity * time;
  }
}
class Spaceship
{
  public var renderData:IRenderable;
  public var moveData:IMoveable;
}

To solve this, we need to ensure that both class instances reference the same instances of these properties. In Actionscript that means these properties must be objects, because objects can be passed by reference while primitives are passed by value.

So we introduce another set of classes, which we’ll call components. These components are just value objects that wrap properties into objects for sharing between processes.

class PositionComponent
{
  public var x:Number;
  public var y:Number;
  public var rotation:Number;
}
class VelocityComponent
{
  public var velocityX:Number;
  public var velocityY:Number;
  public var angularVelocity:Number;
}
class DisplayComponent
{
  public var view:DisplayObject;
}
class Renderable implements IRenderable
{
  public var display:DisplayComponent;
  public var position:PositionComponent;

  public function render():void
  {
    display.view.x = position.x;
    display.view.y = position.y;
    display.view.rotation = position.rotation;
  }
}
class Moveable implements IMoveable
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;

  public function move( time:Number ):void
  {
    position.x += velocity.velocityX * time;
    position.y += velocity.velocityY * time;
    position.rotation += velocity.angularVelocity * time;
  }
}

When we create the spaceship we ensure the Moveable and Renderable instances share the same instance of the PositionComponent.

class Spaceship
{
  public function Spaceship()
  {
    moveData = new Moveable();
    renderData = new Renderable();
    moveData.position = new PositionComponent();
    moveData.velocity = new VelocityComponent();
    renderData.position = moveData.position;
    renderData.display = new DisplayComponent();
  }
}

The processes remain unaffected by this change.

A good place to pause

At this point we have a neat separation of tasks. The game loop cycles through the processes, calling the update method on each one. Each process contains a collection of objects that implement the interface it operates on, and will call the appropriate method of those objects. Those objects each do a single important task on their data. Through the system of components, those objects are able to share data and thus the combination of multiple processes can produce complex updates in the game entities, while keeping each process relatively simple.

This architecture is similar to a number of entity systems in game development. The architecture follows good object-oriented principles and it works. But there’s more to come, starting with a moment of madness.

Abandoning good object-oriented practice

The current architecture uses good object-oriented practices like encapsulation and single responsibility – the IRenderable and IMoveable implementations encapsulate the data and logic for single responsibilities in the updating of game entities every frame – and composition – the Spaceship entity is created by combining implementations of the IRenderable and IMoveable interfaces. Through the system of components we ensured that, where appropriate, data is shared between the different data classes of the entities.

The next step in this evolution of entity systems is somewhat counter-intuitive, breaking one of the core tenets of object-oriented programming. We break the encapsulation of the data and logic in the Renderable and Moveable implementations. Specifically, we remove the logic from these classes and place it in the processes instead.

So this

interface IRenderable
{
  function render();
}
class Renderable implements IRenderable
{
  public var display:DisplayComponent;
  public var position:PositionComponent;

  public function render():void
  {
    display.view.x = position.x;
    display.view.y = position.y;
    display.view.rotation = position.rotation;
  }
}
class RenderProcess implements IProcess
{
  private var targets:Vector.<IRenderable>;

  public function update( time:Number ):void
  {
    for each( var target:IRenderable in targets )
    {
      target.render();
    }
  }
}

Becomes this

class RenderData
{
  public var display:DisplayComponent;
  public var position:PositionComponent;
}
class RenderProcess implements IProcess
{
  private var targets:Vector.<RenderData>;

  public function update( time:Number ):void
  {
    for each( var target:RenderData in targets )
    {
      target.display.view.x = target.position.x;
      target.display.view.y = target.position.y;
      target.display.view.rotation = target.position.rotation;
    }
  }
}

And this

interface IMoveable
{
  function move( time:Number );
}
class Moveable implements IMoveable
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;

  public function move( time:Number ):void
  {
    position.x += velocity.velocityX * time;
    position.y += velocity.velocityY * time;
    position.rotation += velocity.angularVelocity * time;
  }
}
class MoveProcess implements IProcess
{
  private var targets:Vector.<IMoveable>;

  public function move( time:Number ):void
  {
    for each( var target:Moveable in targets )
    {
      target.move( time );
    }
  }
}

Becomes this

class MoveData
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;
}
class MoveProcess implements IProcess
{
  private var targets:Vector.<MoveData>;

  public function move( time:Number ):void
  {
    for each( var target:MoveData in targets )
    {
      target.position.x += target.velocity.velocityX * time;
      target.position.y += target.velocity.velocityY * time;
      target.position.rotation += target.velocity.angularVelocity * time;
    }
  }
}

It’s not immediately clear why we’d do this, but bear with me. On the surface, we’ve removed the need for the interface, and we’ve given the process something more important to do – rather than simply delegate its work to the IRenderable or IMoveable implementations, it does the work itself.

The first apparent consequence of this is that all entities must use the same rendering method, since the render code is now in the RenderProcess. But that’s not actually the case. We could, for example, have two processes, RenderMovieClip and RenderBitmap for example, and they could operate on different sets of entities. So we haven’t lost any flexibility.

What we gain is the ability to refactor our entities significantly to produce an architecture with clearer separation and simpler configuration. The refactoring starts with a question.

Do we need the data classes?

Currently, our entity

class Spaceship
{
  public var moveData:MoveData;
  public var renderData:RenderData;
}

Contains two data classes

class MoveData
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;
}
class RenderData
{
  public var display:DisplayComponent;
  public var position:PositionComponent;
}

These data classes in turn contain three components

class PositionComponent
{
  public var x:Number;
  public var y:Number;
  public var rotation:Number;
}
class VelocityComponent
{
  public var velocityX:Number;
  public var velocityY:Number;
  public var angularVelocity:Number;
}
class DisplayComponent
{
  public var view:DisplayObject;
}

And the data classes are used by the two processes

class MoveProcess implements IProcess
{
  private var targets:Vector.<MoveData>;

  public function move( time:Number ):void
  {
    for each( var target:MoveData in targets )
    {
      target.position.x += target.velocity.velocityX * time;
      target.position.y += target.velocity.velocityY * time;
      target.position.rotation += target.velocity.angularVelocity * time;
    }
  }
}
class RenderProcess implements IProcess
{
  private var targets:Vector.<RenderData>;

  public function update( time:Number ):void
  {
    for each( var target:RenderData in targets )
    {
      target.display.view.x = target.position.x;
      target.display.view.y = target.position.y;
      target.display.view.rotation = target.position.rotation;
    }
  }
}

But the entity shouldn’t care about the data classes. The components collectively contain the state of the entity. The data classes exist for the convenience of the processes. So we refactor the code so the spaceship entity contains the components rather than the data classes.

class Spaceship
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;
  public var display:DisplayComponent;
}
class PositionComponent
{
  public var x:Number;
  public var y:Number;
  public var rotation:Number;
}
class VelocityComponent
{
  public var velocityX:Number;
  public var velocityY:Number;
  public var angularVelocity:Number;
}
class DisplayComponent
{
  public var view:DisplayObject;
}

By removing the data classes, and using the constituent components instead to define the spaceship, we have removed any need for the spaceship entity to know what processes may act on it. The spaceship now contains the components that define its state. Any requirement to combine these components into other data classes for the processes is some other class’s responsibility.

Systems and Nodes

Some core code within the entity system framework (which we’ll get to in a minute) will dynamically create these data objects as they are required by the processes. In this reduced context, the data classes will be mere nodes in the collections (arrays, linked-lists, or otherwise, depending on the implementation) used by the processes. So to clarify this we’ll rename them as nodes.

class MoveNode
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;
}
class RenderNode
{
  public var display:DisplayComponent;
  public var position:PositionComponent;
}

The processes are unchanged, but in keeping with the more common naming I’ll also change their name and call them systems.

class MoveSystem implements ISystem
{
  private var targets:Vector.<MoveNode>;

  public function update( time:Number ):void
  {
    for each( var target:MoveNode in targets )
    {
      target.position.x += target.velocity.velocityX * time;
      target.position.y += target.velocity.velocityY * time;
      target.position.rotation += target.velocity.angularVelocity * time;
    }
  }
}
class RenderSystem implements ISystem
{
  private var targets:Vector.<RenderNode>;

  public function update( time:Number ):void
  {
    for each( var target:RenderNode in targets )
    {
      target.display.view.x = target.position.x;
      target.display.view.y = target.position.y;
      target.display.view.rotation = target.position.rotation;
    }
  }
}
interface ISystem
{
  function update( time:Number ):void;
}

And what is an entity?

One last change – there’s nothing special about the Spaceship class. It’s just a container for components. So we’ll just call it Entity and give it a collection of components. We’ll access those components based on their class type.

class Entity
{
  private var components : Dictionary;
  
  public function add( component:Object ):void
  {
    var componentClass : Class = component.constructor;
    components[ componentClass ] = component'
  }
  
  public function remove( componentClass:Class ):void
  {
    delete components[ componentClass ];
  }
  
  public function get( componentClass:Class ):Object
  {
    return components[ componentClass ];
  }
}

So we’ll create our spaceship like this

public function createSpaceship():void
{
  var spaceship:Entity = new Entity();
  var position:PositionComponent = new PositionComponent();
  position.x = Stage.stageWidth / 2;
  position.y = Stage.stageHeight / 2;
  position.rotation = 0;
  spaceship.add( position );
  var display:DisplayComponent = new DisplayComponent();
  display.view = new SpaceshipImage();
  spaceship.add( display );
  engine.add( spaceship );
}

The core Engine class

We mustn’t forget the system manager, formerly called the process manager.

class SystemManager
{
  private var systems:PrioritisedList;

  public function addSystem( system:ISystem, priority:int ):void
  {
    systems.add( system, priority );
    system.start();
  }

  public function update( time:Number ):void
  {
    for each( var system:ISystem in systemes )
    {
      system.update( time );
    }
  }

  public function removeSystem( system:ISystem ):void
  {
    system.end();
    systems.remove( system );
  }
}

This will be enhanced and will sit at the heart of our entity component system framework. We’ll add to it the functionality mentioned above to dynamically create nodes for the systems.

The entities only care about components, and the systems only care about nodes. So to complete the entity component system framework, we need code to watch the entities and, as they change, add and remove their components to the node collections used by the systems. Because this is the one bit of code that knows about both entities and systems, we might consider it central to the game. In Ash, I call this the Engine class, and it is an enhanced version of the system manager.

Every entity and every system is added to and removed from the Engine class when you start using it and stop using it. The Engine class keeps track of the components on the entities and creates and destroys nodes as necessary, adding those nodes to the node collections. The Engine class also provides a way for the systems to get the collections they require.

public class Engine
{
  private var entities:EntityList;
  private var systems:SystemList;
  private var nodeLists:Dictionary;

  public function addEntity( entity:Entity ):void
  {
    entities.add( entity );
    // create nodes from this entity's components and add them to node lists
    // also watch for later addition and removal of components from the entity so
    // you can adjust its derived nodes accordingly
  }

  public function removeEntity( entity:Entity ):void
  {
    // destroy nodes containing this entity's components
    // and remove them from the node lists
    entities.remove( entity );
  }

  public function addSystem( system:System, priority:int ):void
  {
    systems.add( system, priority );
    system.start();
  }

  public function removeSystem( system:System ):void
  {
    system.end();
    systems.remove( system );
  }

  public function getNodeList( nodeClass:Class ):NodeList
  {
    var nodes:NodeList = new NodeList();
    nodeLists[ nodeClass ] = nodes;
    // create the nodes from the current set of entities
    // and populate the node list
    return nodes;
  }

  public function update( time:Number ):void
  {
    for each( var system:ISystem in systemes )
    {
      system.update( time );
    }
  }
}

To see one implementation of this architecture, checkout the Ash entity system framework, and see the example Asteroids implementation there too.

A step further

In Actionscript, the Node and Entity classes are necessary for efficiently managing the Components and passing them to the Systems. But note that these classes are just glue, the game is defined in the Systems and the Components. The Entity class provides a means to find and manage the components for each entity and the Node classes provide a means to group components into collections for use in the Systems. In other languages and runtime environments it may be more efficient to manage this glue differently.

For example, in a large server-based game we might store the components in a database – they are just data after all – with each record (i.e. each component) having a field for the unique id of the entity it belongs to along with fields for the other component data. Then we pull the components for an entity directly from the database when needed, using the entity id to find it, and we create collections of data for the systems to operate on by doing joined queries across the appropriate databases. For example, for the move system we would pull records from the postion components table and the movement components table where entity ids match and a record exists in both tables (i.e. the entity has both a position and a movement component). In this instance the Entity and Node classes are not required and the only presence for the entity is the unique id that is used in the data tables.

Similarly, if you have control over the memory allocation for your game it is often more efficient to take a similar approach for local game code too, creating components in native arrays of data and looking-up the components for an entity based on an id. Some aspects of the game code become more complex and slower (e.g. finding the components for a specific entity) but others become much faster (e.g. iterating through the component data collections inside a system) because the data is efficiently laid out in memory to minimise cache misses and maximise speed.

The important elements of this architecture are the components and the systems. Everything else is configuration and glue. And note that components are data and systems are functions, so we don’t even need object oriented code to do this.

Conclusion

So, to summarise, entity component systems originate from a desire to simplify the game loop. From that comes an architecture of components, which represent the state of the game, and systems, which operate on the state of the game. Systems are updated every frame – this is the game loop. Components are combined into entities, and systems operate on the entities that have all the components they are interested in. The engine monitors the systems and the components and ensures each system has access to a collection of all the components it needs.

An entity component system framework like Ash provides the basic scaffolding and core management for this architecture, without providing any actual component or system classes. You create your game by creating the appropriate components and systems.

An entity component system game engine will provide many standard systems and components on top of the basic framework.

Three entity component system frameworks for Actionscript are my own Ash, Ember2 by Tom Davies and Xember by Alec McEachran. Artemis is an entity system framework for Java, that has also been ported to C#.

My next post covers some of the reasons why I like using an entity system framework for my game development projects.

Share this post or a comment online –

Why use an Entity Component System architecture for game development?

Posted on

Following my previous post on entity systems for game development I received a number of good questions from developers. I answered many of them directly to the questioners but one question stands out. It’s all very well explaining what an entity component system framework is, and even building one, but why would you want to use one? In particular, why use the later component/system architecture I described and that I implement in Ash rather than the earlier object-oriented entity architecture as used, for example, in PushButton Engine.

So, in this post I will look more at what the final architecture is, what it gives us that other architectures don’t, and why I personally prefer this architecture.

The core of the architecture

First, it’s worth noting that the core of this architecture is the components and the systems. Components are value-objects that contain the state of the game, and systems are the logic that operates on that state, changing it as the game progresses. The other elements of the architecture are purely incidental, designed to make life easier.

The entity object is present to collect related components together. The relation between components is encapsulated by the concept of an entity and that is vital to the architecture, but it isn’t necessary to use an explicit Entity object for this. There are some frameworks that simply use an id to represent the entity, adding the entity id to every component to indicate which entity it belongs to.

As a concept, the entity is vital to the architecture. But as a code construct it is entirely optional. I include it because, when using an object-oriented language, the entity object makes life easier. In particular, it enables us to create the methods that operate on the entity as methods of an entity object and to track and manage the entity through this object, removing the need to track ids throughout the code.

While the concept of an entity is vital to the architecture, the concept of node objects is entirely incidental. The nodes are used as the objects in the collections of components supplied to the systems. We could instead provide each system with a collection of the relevant entities and let the systems pull the components they want to operate on out of the entities, using the get() method of the entity.

In Ash, the nodes serve two purposes. First they enable us to use a more efficient data structure in which the node objects that the systems receive are nodes in a linked list. This improves the execution speed of the framework.

Second, using the node objects enables us to apply strong, static typing throughout our code. The method to fetch a component from an entity necessarily returns an untyped object, which must then be cast to the correct component type for use in the game code. The properties on the node are already statically typed to the components’ data types, so no casting is necessary.

So, fundamentally, the entity architecture is about components and systems.

This is not object-oriented programming

We can build our entity architecture using an object-oriented language but, on a fundamental level, this is not object-oriented programming. The architecture is not about objects, it’s about data (components) and sub-routines that operate on that data (systems).

For many object-oriented programmers this is the hardest part of working with an entity system framework. Our tendency is to fall back to what we know and as an object-oriented programmer using an object-oriented language that means encapsulating data and operations together into objects. If you do this with a framework like Ash you will fail.

Data-Oriented Programming

Games tend to be about lots of fast changing state, with players, non-player characters, game objects like bullets and lasers, bats and balls, tables and chairs, and levels, scores, lives and more all having state that might include position, rotation, speed, acceleration, weight, colour, intention, goals, desires, friendships, enemies and more.

The state of the game can be encapsulated in this large mass of constantly changing data, and on a technical level the game is entirely about what this data is and how this data changes.

In a game a single little piece of this data may have many operations acting on it. Take, for example, a player character that has a position property that represents the character’s position in the game world. This single piece of data may be used by

  • The render system, to draw the player in the world.
  • The camera system, to position the camera relative to the player.
  • The AI systems of all non-player characters, to decide how they should react to the player.
  • The input system, which alters the player’s position based on user input.
  • The physics system, which alters the player’s position based on the physics of the game world.
  • The collision system, which tests whether the player is colliding with other objects and resolves those collisions.

and probably many more systems besides. If we try to build our game using objects that encapsulate data with the operations that act on that data, then we will build dependencies between all these different systems as they all want to be encapsulated with the player’s position data. This can’t be done unless we code the game as one single, massive class, so inevitably we break some parts of the game into separate systems and provide data to those systems – the physics system, the graphics system – while including other elements of the game logic within the game objects themselves.

An entity architecture based on components and systems takes the idea of discrete systems to its logical conclusion. All operations are programmed as independent systems, and all game state is stored separately in a set of data components, which are provided to the systems according to their need.

The systems are decoupled from each other. Each system knows only about itself and the data it operates on. It knows and cares nothing at all about the other systems and how they be affected by or use the data before or after this system gets to work with it.

Also, by embracing the system as the core logic of the architecture, we are encouraged to make many smaller and simpler systems rather than a few large complex ones, which again leads to simpler code and looser coupling.

This decoupling makes building your game much easier. It is why I enjoy working with this form of entity system so much, and why I built Ash.

Storing the game state

Another benefit of the component/system architecture is apparent when you want to save and restore the game state. Because the game state is contained entirely in the components, and because these are simple value objects, saving the game state is a relatively simple matter of serialising out the components, and restoring the game state involves just deserialising the data back in again.

In most cases, serialising a value-object is straightforward, and one could simply json-encode each component, with additional data to indicate its entity owner (an id) and its component type (a string), to save the game state.

Adam Martin wrote about comparing components in an entity system framework to data in a relational database (there’s lots of interesting entity related stuff on Adam’s blog), and emphasising that conversion between a relational database for long-term storage and components for game play doesn’t require any object/relational mapping, because components are simple copies of the relational database’s data structure rather than complex objects.

This leads further to the conclusion that a component/system architecture is ideal for an MMO game, since state will be stored in a relational database on the game servers, and much of the processing of that state will occur on the servers, where using a set of discrete, independent systems to process the data as the game unfolds is an excellent fit to both the data storage requirements of the state and the parallelism available on the servers.

Concurrency

Indeed, a component/system architecture is well suited to applying concurrency to a game. In most games, some of the systems are entirely independent of each other, including being independent of the order in which they are applied. This makes it easy to run these systems in parallel.

Further, most systems consist of a loop in which all nodes are processed sequentially. In many cases, the loop can be parallelised since the nodes can be updated independently of each other.

This gives us two places in the code where concurrency can be applied without altering the core logic of the game, which is inside the loop in the systems, or the core state of the game, which is in the components.

This makes adding concurrency to the game relatively simple.

We don’t need object-orientation

Finally, because the component/system architecture is not object-oriented, it lends itself to other programming languages that implement different programming paradigms like functional programming and procedural programming. While I created Ash as an Actionscript framework, this architecture would be well suited to Javascript for client side development or any of the many functional languages used for highly concurrent server side development.

Update: In-game editors

Tom Davies has pointed out that a very valuable benefit to him is how easy it is to create an in-game level editor when developing with an entity system framework like Ember or Ash. You can see his example here.

The complete separation of the game state and the game logic in an entity system framework makes it easy to create an editor that lets you alter the state (configuration, level design, AI, etc.) while playing the game. Add to this the easier saving and loading of state and you have a framework that is very well suited to in-game editing.

How to Build an Entity Component System Game in Javascript

Game Development
Posted on Aug 3rd, 2014

Rectangle Eater

View the source code or play Rectangle Eater

Creating and manipulating abstractions is the essence of programming. There is no “correct” abstraction to solve a problem, but some abstractions are better suited for certain problems than others. Class-based, Object Oriented Programming (OOP), is the most widely used paradigm for organizing programs. There are others. Prototypical based languages, like Javascript, provide a different way of thinking around how to solve problems. Functional programming provides yet another completely different way to think about and solve problems. Programming languages are just one area where a different mindset can help solve problems better.

Even within a class based or prototype based language, many methods exist for structuring code. One approach I’ve grown to love is a more data driven approach to code. One such technique is Entity-Component-System (ECS). While it is a general architecture pattern that could be applied to many domains, the predominant uses of it are in game development. In this post, I’ll cover the basic topics of ECS and we’ll build a basic HTML5 game about eating rectangles – oh-so creatively called “Rectangle Eater”.

Entity-Component-System

Discovering Entity Component System (ECS) was an “ah-hah” moment for me. With ECS, entities are just collections of components; just a collection of data.

  • Entity: An entity is just an ID
  • Component: Components are just data.
  • System: Logic that runs on every entity that has a component of the system. For example, a “Renderer” system would draw all entities that have a “appearance” component.

With this approach, you avoid having to create gnarly inheritance chains. With this approach, for example, a half-orc isn’t some amalgamation of a human class and an orc class (which might inherit from a Monster class). With this approach, a half-orc is just a grouping of data.

An entity is just a like a record in a database. The components are the actual data. Here’s a high level example of what the data might look like for entities, shown by ID and components. The beauty of this system is that you can dynamically build entities – an entity can have whatever components (data) you want.


|         | component-health  | component-position |  component-appearance |
|---------|-------------------|--------------------|-----------------------|
|entity1  | 100               | {x: 0, y: 0}       | {color: green}        |
|entity2  |                   | {x: 0, y: 0}       |                       |
|entity3  |                   |                    | {color: blue}         |

Dynamic Data Driven Design

Everything is tagged as an entity. A bullet, for instance, might just have a “physics” and “appearance” component. Entity Component System is data driven. This approach allows greater flexibility and more expression. One benefit is the ability to dynamically add and remove components, even at run time. You could dynamically remove the appearance component to make invisible bullets, or add a “playerControllable” component to allow the bullet to be controlled by the player. No new classes required.

This can potentially be a problem as systems have to iterate through all entities. Of course, it’s not terribly difficult to optimize and structure code so not all entities are hit each iteration if you have too many, but it’s helpful to keep this constraint in mind, especially for browser based games.

Assemblages

One benefit of a Class based approach is the ability to easily create multiple objects of the same type. If I want one hundred orcs, I can just create a hundred orc objects and know what properties they’ll all have. This can be accomplished with ECS through an abstraction called an assemblage, which is just a way to easily create entities that have some grouping of components. For instance, a Human assemblage might contain “position”, “name”, “health”, and “appearance” components. A Sword assemblage might just have “appearance” and “name”.

One benefit this provides over normal Class inheritance is the ability to easily add on (or remove) components from assemblages. Since it’s data driven, you can manipulate and change them programmatically based on whatever parameters you desire. Maybe you want to create a ton of humans but have some of them be invisible – no need for a new class, just remove the “appearance” component from that entity.

Code

This is not an attempt to build out a robust ECS library. This is designed to be an overview of Entity Component System implemented in Javascript. It’s not the best or most optimized way to do it; but it can provide a foundation for a concrete understanding of how everything fits together. All code can be found on github.

Entity

The abstraction is that an entity is just an ID; a container of components. Let’s start by creating a function which we can create entities from. Each entity will have just an id and components property. (Note: the follow expects a global ECS object to exist, which looks like var ECS = {};)

ECS.Entity = function Entity(){
    // Generate a pseudo random ID
    this.id = (+new Date()).toString(16) + 
        (Math.random() * 100000000 | 0).toString(16) +
        ECS.Entity.prototype._count;

    // increment counter
    ECS.Entity.prototype._count++;

    // The component data will live in this object
    this.components = {};

    return this;
};
// keep track of entities created
ECS.Entity.prototype._count = 0;

ECS.Entity.prototype.addComponent = function addComponent ( component ){
    // Add component data to the entity
    // NOTE: The component must have a name property (which is defined as 
    // a prototype protoype of a component function)
    this.components[component.name] = component;
    return this;
};
ECS.Entity.prototype.removeComponent = function removeComponent ( componentName ){
    // Remove component data by removing the reference to it.
    // Allows either a component function or a string of a component name to be
    // passed in
    var name = componentName; // assume a string was passed in

    if(typeof componentName === 'function'){ 
        // get the name from the prototype of the passed component function
        name = componentName.prototype.name;
    }

    // Remove component data by removing the reference to it
    delete this.components[name];
    return this;
};

ECS.Entity.prototype.print = function print () {
    // Function to print / log information about the entity
    console.log(JSON.stringify(this, null, 4));
    return this;
};

View Source

To create a new entity, we’d simply call it like: var entity = new ECS.Entity();.

There’s not a lot going on in the code here. First, in the function itself, we generate an ID based on the current time, a call to Math.random(), and a counter based on the total number of created entities. This ensures we get a unique ID for each entity. We increment the counter (prototype properties are shared across all object instances; sort of similar to a class variable). Then, we create an empty object to stick components (the data) in.

We expose an addComponent and removeComponent function on the prototype (again, single functions in memory shared across all object instances). Each take in a component object and add or remove the passed in component from the Entity. Lastly, the print method simply JSON-ifies the entity, providing all the data. We could use this to dump out and reload data later (e.g., saving).

So, at the core, an Entity is little more than an object with some data properties. We’ll cover how to create multiple Entities soon, and where assemblages fit in.

Component

Here’s where the data part of data driven programming kicks in. I’ve structured components similarly to entities; for example:

ECS.Components.Health = function ComponentHealth ( value ){
    value = value || 20;
    this.value = value;

    return this;
};
ECS.Components.Health.prototype.name = 'health';

To get a Health component, you’d simply create it with new ECS.Components.Health( VALUE ) where VALUE is an optional starting value (20 if nothing is passed in). Importantly, there is a name property on the prototype which tells the Entity what to call the component. For example, to create an entity then give it a health component:

var entity = new ECS.Entity();
entity.addComponent( new ECS.Components.Health() );

That’s all that is required to add a component to an entity. If we printed the entity out now (entity.print();), we’d see something like:

{
    "id": "1479f3d15bd4bf98f938300430178",
    "components": {
        "health": {
            "value": 20
        }
    }
} 

That’s it – it’s just data! We could change the entity’s health by modifying it directly, e.g., entity.components.health.value = 40; We can have any kind of data nesting we want; for example, if we created a position component with x and y data values, we’d get as output:


{
    "id": "1479f3d15bd4bf98f938300430178",
    "components": {
        "health": {
            "value": 20
        },
        "position": {
            "x": 426,
            "y": 98
        }
    }
} 

To keep this post manageable, here’s all the code for all these components used in the game

Since components are just data, that don’t have any logic. (Depending on what works for you, you could add some prototype functions to components that would aide in data calculations, but it’s helpful to view components just as data). So we have a bunch of data now, but to do anything interesting we need to run operations on it. That’s where Systems come in.

System

Systems run your game’s logic. They take in entities and run operations on entities that have specific components the system requires. This way of thinking is a bit inverted from typical Class based programming.

In Class based programming, to model a cat, a Cat Class would exist. You’d create cat objects and to get the cat to meow, you’d call the speak() method. The functionality lives inside of the object. The object is not just data, but also functionality.

With ECS, to model a Cat you’d first create an entity. Then, you’d add some components that cats have (size, name, etc.). If you wanted the entity to be able to meow, maybe you’d give it a speak component with a value of “meow”. The distinction here though is that this is just data – maybe it looks like:

{
    "id": "f279f3d85bd4bf98f938300430178",
    "components": {
        "speak": {
            "sound": "meeeooowww"
        }
    }
}

The entity can do nothing by itself. So, to get a “cat” entity to speak, you’d use a speak System. (Note: the component name and system name do not have to be 1:1, this is just an example. Most systems use multiple different components). The system would look for all entities that have a speak component, then run some logic – plugging in the entity’s data.

The functionality happens in Systems, not on the objects themselves. You’ll have many different systems that are tailored for your game. Systems are where your main game logic lives. For our rectangle eating game, we only need a few systems: collision, decay, render, and userInput.

The way I’ve sturctured systems is to take in all entities (here, the entities are an object of key:value pairs of entityId: entityObject). Let’s take a look at a snippet of the render system. Note, the systems are just functions that take in entities.

ECS.systems.render = function systemRender ( entities ) {
    // Here, we've implemented systems as functions which take in an array of
    // entities. An optimization would be to have some layer which only 
    // feeds in relevant entities to the system, but for demo purposes we'll
    // assume all entities are passed in and iterate over them.

    // This happens each tick, so we need to clear out the previous rendered
    // state
    clearCanvas();

    var curEntity, fillStyle; 

    // iterate over all entities
    for( var entityId in entities ){
        curEntity = entities[entityId];

        // Only run logic if entity has relevant components
        //
        // For rendering, we need appearance and position. Your own render 
        // system would use whatever other components specific for your game
        if( curEntity.components.appearance && curEntity.components.position ){

            // Build up the fill style based on the entity's color data
            fillStyle = 'rgba(' + [
                curEntity.components.appearance.colors.r,
                curEntity.components.appearance.colors.g,
                curEntity.components.appearance.colors.b
            ];

            if(!curEntity.components.collision){
                // If the entity does not have a collision component, give it 
                // some transparency
                fillStyle += ',0.1)';
            } else {
                // Has a collision component
                fillStyle += ',1)';
            }

            ECS.context.fillStyle = fillStyle;

            // Color big squares differently
            if(!curEntity.components.playerControlled &&
            curEntity.components.appearance.size > 12){
                ECS.context.fillStyle = 'rgba(0,0,0,0.8)';
            }

            // draw a little black line around every rect
            ECS.context.strokeStyle = 'rgba(0,0,0,1)';

            // draw the rect
            ECS.context.fillRect( 
                curEntity.components.position.x - curEntity.components.appearance.size,
                curEntity.components.position.y - curEntity.components.appearance.size,
                curEntity.components.appearance.size * 2,
                curEntity.components.appearance.size * 2
            );
            // stroke it
            ECS.context.strokeRect(
                curEntity.components.position.x - curEntity.components.appearance.size,
                curEntity.components.position.y - curEntity.components.appearance.size,
                curEntity.components.appearance.size * 2,
                curEntity.components.appearance.size * 2
            );
        }
    }
};

The logic here is simple. First, we clear the canvas before doing anything. Then, we iterate over all entities. This system renders entities, but we only care about entities that have an appearance and position. In our game, all entities have these components – but if we wanted to create invisible rectangles that the player could interact with, all we’d have to do is remove the appearance component. So, after we’ve found the entities which contain the relevant data for the system, we can do operations on them.

In this system, we just render the entity based on the colors properties in the appearance component. One benefit too is that we don’t have to set all the appearance properties here – we might set some in the collision system, or in the health system, or in the decay system; we have complete flexibility over what roles we want to assign to each system. Because the systems are driven by data, we don’t have to limit our thinking to just “methods on classes and objects.” We can have as many systems as want, as complex or simple as we want that target whatever kinds of entities we want.

Overview of Rectangle Eater’s systems:

  • collision: Handles collision, updating the data for health on collision, and removing / adding new entities (rectangles). Bulk of the game’s logic.
  • decay: Handles rectangles getting small and losing health. Any entity with a health component (e.g., most rectangles and the player controlled rectangle) will be affected. This is where a lot of the “fun” configuration happens. If the rectangle decays and goes away too fast then the game is too hard – if it’s too slow, it’s not fun.
  • render: Handles rendering entities based on their appearance component.
  • userInput: Allows the player to move around entities that have a PlayerControlled component.

In the collision system of our game, we check for collisions between the user controlled entity (specified by a PlayerControlled component and handled via the userInput system) and all other entities with a collision component. If a collision occurs, we update the entity’s health (via the health component), remove the collided entity immediately (the systems are data driven – there’s no problem dynamically adding or removing entities on a per system level), then finally randomly add some new rectangles (most of these will decay over time, and when they get smaller they give you more health when you collide with them – something else we check for in this collision system).

Like in a normal game loop, the order which the systems gets called is also important. If your render before the decay system is called, for example, you’ll always be a tick behind.

Gluing it all together

The final step involves connecting all the pieces together. For our game, we just need to do a few things:

  1. Setup the initial entities
  2. Setup the order of the systems which we want to use
  3. Setup a game loop, which calls each system and passed in all the entities
  4. Setup a lose condition

1. Let’s take a look at the code for setting up the initial entities and the player entity:

var self = this;
var entities = {}; // object containing { id: entity  }
var entity;

// Create a bunch of random entities
for(var i=0; i < 20; i++){
    entity = new ECS.Entity();
    entity.addComponent( new ECS.Components.Appearance());
    entity.addComponent( new ECS.Components.Position());

    // % chance for decaying rects
    if(Math.random() < 0.8){
        entity.addComponent( new ECS.Components.Health() );
    }

    // NOTE: If we wanted some rects to not have collision, we could set it
    // here. Could provide other gameplay mechanics perhaps?
    entity.addComponent( new ECS.Components.Collision());

    entities[entity.id] = entity;
}

// PLAYER entity
// Make the last entity the "PC" entity - it must be player controlled,
// have health and collision components
entity = new ECS.Entity();
entity.addComponent( new ECS.Components.Appearance());
entity.addComponent( new ECS.Components.Position());
entity.addComponent( new ECS.Components.Collision() );
entity.addComponent( new ECS.Components.PlayerControlled() );
entity.addComponent( new ECS.Components.Health() );

// we can also edit any component, as it's just data
entity.components.appearance.colors.g = 255;
entities[entity.id] = entity;

// store reference to entities
ECS.entities = entities;

Note how we can modify any of the component data directly. It’s all data that can be manipulated however and whenever you want! The player entity step could be even further simplified by using assemblages, which are basically entity templates. For instance (using our assemblages):

entity = new ECS.Assemblages.CollisionRect();
entity.addComponent( new ECS.Components.Health());
entity.addComponent( new ECS.Components.PlayerControlled() );

2. Next, we setup the order of the systems:

// Setup systems
// Setup the array of systems. The order of the systems is likely critical, 
// so ensure the systems are iterated in the right order
var systems = [
    ECS.systems.userInput,
    ECS.systems.collision,
    ECS.systems.decay, 
    ECS.systems.render
];

3. Then, a simple game loop

// Game loop
function gameLoop (){
    // Simple game loop
    for(var i=0,len=systems.length; i < len; i++){
        // Call the system and pass in entities
        // NOTE: One optimal solution would be to only pass in entities
        // that have the relevant components for the system, instead of 
        // forcing the system to iterate over all entities
        systems[i](ECS.entities);
    }

    // Run through the systems. 
    // continue the loop
    if(self._running !== false){
        requestAnimationFrame(gameLoop);
    }
}
// Kick off the game loop
requestAnimationFrame(gameLoop);

4. Finally, a lose condition

// Lose condition
this._running = true; // is the game going?
this.endGame = function endGame(){ 
    self._running = false;
    document.getElementById('final-score').innerHTML = +(ECS.$score.innerHTML);
    document.getElementById('game-over').className = '';

    // set a small timeout to make sure we set the background
    setTimeout(function(){
        document.getElementById('game-canvas').className = 'game-over';
    }, 100);
};

View on github

Now, we can kick off the game (provided the html has been set up)!

Play Rectangle Eater Rectangle Eater

Conclusion

Programming is a complex endeavor by nature. We program in abstractions, and different frameworks for thinking can make certain problems easier to solve. Data driven programming is one framework for thinking of how to write programs. It’s not the best fit for all problems, but can make some problems much easier to solve and understand. Thinking of code as data is a powerful concept. Entity Component System is a pattern that fits game development well. Try taking the passenger seat. Try letting data drive your code.

Posted on 

Last week I released Ash, an entity component system framework for Actionscript game development, and a number of people have asked me the question “What is an entity component system framework?”. This is my rather long answer.

Entity systems are growing in popularity, with well-known examples like Unity, and lesser known frameworks like Actionscript frameworks Ember2Xember and my own Ash. There’s a very good reason for this; they simplify game architecture, encourage clean separation of responsibilities in your code, and are fun to use.

In this post I will walk you through how an entity based architecture evolves from the old fashioned game loop. This may take a while. The examples will be in Actionscript because that happens to be what I’m using at the moment, but the architecture applies to all programming language.

Note that the naming of things within this post is based on

  • How they were named as I discovered these archtectures over the past twenty years of my game development life
  • How they are usually named in modern entity component system architectures

This is different, for example, to how they are named in Unity, which is an entity architecture but is not an entity component system architecture.

This is based on a presentation I gave at try{harder} in 2011.

The examples

Throughout this post, I’ll be using a simple Asteroids game as an example. I like to use Asteroids as an example because it involves simplified versions of many of the systems required in larger games – rendering, physics, ai, user control of a character, non-player characters.

The game loop

To understand why we use entity systems, you really need to understand the old-fashioned game loop. A game loop for Asteroids might look something like this

function update( time:Number ):void
{
  game.update( time );
  spaceship.updateInputs( time );
  for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
  {
    flyingSaucer.updateAI( time );
  }
  spaceship.update( time );
  for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
  {
    flyingSaucer.update( time );
  }
  for each( var asteroid:Asteroid in asteroids )
  {
    asteroid.update( time );
  }
  for each( var bullet:Bullet in bullets )
  {
    bullet.update( time );
  }
  collisionManager.update( time );
  spaceship.render();
  for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
  {
    flyingSaucer.render();
  }
  for each( var asteroid:Asteroid in asteroids )
  {
    asteroid.render();
  }
  for each( var bullet:Bullet in bullets )
  {
    bullet.render();
  }
}

This game loop is called on a regular interval, usually every 60th of a second or every 30th of a second, to update the game. The order of operations in the loop is important as we update various game objects, check for collisions between them, and then draw them all. Every frame.

This is a very simple game loop. It’s simple because

  1. The game is simple
  2. The game has only one state

In the past, I have worked on console games where the game loop, a single function, was over 3,000 lines of code. It wasn’t pretty, and it wasn’t clever. That’s the way games were built and we had to live with it.

Entity system architecture derives from an attempt to resolve the problems with the game loop. It addresses the game loop as the core of the game, and pre-supposes that simplifying the game loop is more important than anything else in modern game architecture. More important than separation of the view from the controller, for example.

Processes

The first step in this evolution is to think about objects called processes. These are objects that can be initialised, updated on a regular basis, and destroyed. The interface for a process looks something like this.

interface IProcess
{
  function start():Boolean;
  function update( time:Number ):void;
  function end():void;
}

We can simplify our game loop if we break it into a number of processes to handle, for example, rendering, movement, collision resolution. To manage those processes we create a process manager.

class ProcessManager
{
  private var processes:PrioritisedList;
  public function addProcess( process:IProcess, priority:int ):Boolean
  {
    if( process.start() )
    {
      processes.add( process, priority );
      return true;
    }
    return false;
  }
  public function update( time:Number ):void
  {
    for each( var process:IProcess in processes )
    {
      process.update( time );
    }
  }
  public function removeProcess( process:IProcess ):void
  {
    process.end();
    processes.remove( process );
  }
}

This is a somewhat simplified version of a process manager. In particular, we should ensure we update the processes in the correct order (identified by the priority parameter in the add method) and we should handle the situation where a process is removed during the update loop. But you get the idea. If our game loop is broken into multiple processes, then the update method of our process manager is our new game loop and the processes become the core of the game.

The render process

Lets look at the render process as an example. We could just pull the render code out of the original game loop and place it in a process, giving us something like this

class RenderProcess implements IProcess
{
  public function start() : Boolean
  {
    // initialise render system
    return true;
  }
  public function update( time:Number ):void
  {
    spaceship.render();
    for each( var flyingSaucer:FlyingSaucer in flyingSaucers )
    {
      flyingSaucer.render();
    }
    for each( var asteroid:Asteroid in asteroids )
    {
      asteroid.render();
    }
    for each( var bullet:Bullet in bullets )
    {
      bullet.render();
    }
  }
  public function end() : void
  {
    // clean-up render system
  }
}

Using an interface

But this isn’t very efficient. We still have to manually render all the different types of game object. If we have a common interface for all renderable objects, we can simplify matters a lot.

interface IRenderable
{
  function render();
}
class RenderProcess implements IProcess
{
  private var targets:Vector.<IRenderable>;
  public function start() : Boolean
  {
    // initialise render system
    return true;
  }
  public function update( time:Number ):void
  {
    for each( var target:IRenderable in targets )
    {
      target.render();
    }
  }
  public function end() : void
  {
    // clean-up render system
  }
}

Then our spaceship class might contain some code like this

class Spaceship implements IRenderable
{
  public var view:DisplayObject;
  public var position:Point;
  public var rotation:Number;
  public function render():void
  {
    view.x = position.x;
    view.y = position.y;
    view.rotation = rotation;
  }
}

This code is based on the flash display list. If we were blitting, or using stage3d, it would be different, but the principles would be the same. We need the image to be rendered, and the position and rotation for rendering it. And the render function does the rendering.

Using a base class and inheritance

In fact, there’s nothing in this code that makes it unique to a spaceship. All the code could be shared by all renderable objects. The only thing that makes them different is which display object is assigned to the view property, and what the position and rotation are. So lets wrap this in a base class and use inheritance.

class Renderable implements IRenderable
{
  public var view:DisplayObject;
  public var position:Point;
  public var rotation:Number;
  public function render():void
  {
    view.x = position.x;
    view.y = position.y;
    view.rotation = rotation;
  }
}
class Spaceship extends Renderable
{
}

Of course, all renderable items will extend the renderable class, so we get a simple class heirarchy like this

The move process

To understand the next step, we first need to look at another process and the class it works on. So lets try the move process, which updates the position of the objects.

interface IMoveable
{
  function move( time:Number );
}
class MoveProcess implements IProcess
{
  private var targets:Vector.<IMoveable>;
  public function start():Boolean
  {
    return true;
  }
  public function update( time:Number ):void
  {
    for each( var target:IMoveable in targets )
    {
      target.move( time );
    }
  }
  public function end():void
  {
  }
}
class Moveable implements IMoveable
{
  public var position:Point;
  public var rotation:Number;
  public var velocity:Point;
  public var angularVelocity:Number;
  public function move( time:Number ):void
  {
    position.x += velocity.x * time;
    position.y += velocity.y * time;
    rotation += angularVelocity * time;
  }
}
class Spaceship extends Moveable
{
}

Multiple inheritance

That’s almost good, but unfortunately we want our spaceship to be both moveable and renderable, and many modern programming languages don’t allow multiple inheritance.

Even in those languages that do permit multiple inheritance, we have the problem that the position and rotation in the Moveable class should be the same as the position and rotation in the Renderable class.

One common solution is to use an inheritance chain, so that Moveable extends Renderable.

class Moveable extends Renderable implements IMoveable
{
  public var velocity:Point;
  public var angularVelocity:Number;
  public function move( time:Number ):void
  {
    position.x += velocity.x * time;
    position.y += velocity.y * time;
    rotation += angularVelocity * time;
  }
}
class Spaceship extends Moveable
{
}

Now the spaceship is both moveable and renderable. We can apply the same principles to the other game objects to get this class hierarchy.

We can even have static objects that just extend Renderable.

Moveable but not Renderable

But what if we want a Moveable object that isn’t Renderable? An invisible game object, for example? Now our class hierarchy breaks down and we need an alternative implementation of the Moveable interface that doesn’t extend Renderable.

class InvisibleMoveable implements IMoveable
{
  public var position:Point;
  public var rotation:Number;
  public var velocity:Point;
  public var angularVelocity:Number;
  public function move( time:Number ):void
  {
    position.x += velocity.x * time;
    position.y += velocity.y * time;
    rotation += angularVelocity * time;
  }
}

In a simple game, this is clumsy but manageable, but in a complex game using inheritance to apply the processes to objects rapidly becomes unmanageable as you’ll soon discover items in your game that don’t fit into a simple linear inheritance tree, as with the force-field above.

Favour composition over inheritance

It’s long been a sound principle of object-oriented programming to favour composition over inheritance. Applying that principle here can rescue us from this potential inheritance mess.

We’ll still need Renderable and Moveable classes, but rather than extending these classes to create the spaceship class, we will create a spaceship class that contains an instance of each of these classes.

class Renderable implements IRenderable
{
  public var view:DisplayObject;
  public var position:Point;
  public var rotation:Number;
  public function render():void
  {
    view.x = position.x;
    view.y = position.y;
    view.rotation = rotation;
  }
}
class Moveable implements IMoveable
{
  public var position:Point;
  public var rotation:Number;
  public var velocity:Point;
  public var angularVelocity:Number;
  public function move( time:Number ):void
  {
    position.x += velocity.x * time;
    position.y += velocity.y * time;
    rotation += angularVelocity * time;
  }
}
class Spaceship
{
  public var renderData:IRenderable;
  public var moveData:IMoveable;
}

This way, we can combine the various behaviours in any way we like without running into inheritance problems.

The objects made by this composition, the Static Object, Spaceship, Flying Saucer, Asteroid, Bullet and Force Field, are collectively called entities.

Our processes remain unchanged.

interface IRenderable
{
  function render();
}
class RenderProcess implements IProcess
{
  private var targets:Vector.<IRenderable>;
  public function update(time:Number):void
  {
    for each(var target:IRenderable in targets)
    {
      target.render();
    }
  }
}
interface IMoveable
{
  function move();
}
class MoveProcess implements IProcess
{
  private var targets:Vector.<IMoveable>;
  public function update(time:Number):void
  {
    for each(var target:IMoveable in targets)
    {
      target.move( time );
    }
  }
}

But we don’t add the spaceship entity to each process, we add it’s components. So when we create the spaceship we do something like this

public function createSpaceship():Spaceship
{
  var spaceship:Spaceship = new Spaceship();
  ...
  renderProcess.addItem( spaceship.renderData );
  moveProcess.addItem( spaceship.moveData );
  ...
  return spaceship;
}

This approach looks good. It gives us the freedom to mix and match process support between different game objects without getting into spagetti inheritance chains or repeating ourselves. But there’s one problem.

What about the shared data?

The position and rotation properties in the Renderable class instance need to have the same values as the position and rotation properties in the Moveable class instance, since the Move process will change the values in the Moveable instance and the Render process will use the values in the Renderable instance.

class Renderable implements IRenderable
{
  public var view:DisplayObject;
  public var position:Point;
  public var rotation:Number;
  public function render():void
  {
    view.x = position.x;
    view.y = position.y;
    view.rotation = rotation;
  }
}
class Moveable implements IMoveable
{
  public var position:Point;
  public var rotation:Number;
  public var velocity:Point;
  public var angularVelocity:Number;
  public function move( time:Number ):void
  {
    position.x += velocity.x * time;
    position.y += velocity.y * time;
    rotation += angularVelocity * time;
  }
}
class Spaceship
{
  public var renderData:IRenderable;
  public var moveData:IMoveable;
}

To solve this, we need to ensure that both class instances reference the same instances of these properties. In Actionscript that means these properties must be objects, because objects can be passed by reference while primitives are passed by value.

So we introduce another set of classes, which we’ll call components. These components are just value objects that wrap properties into objects for sharing between processes.

class PositionComponent
{
  public var x:Number;
  public var y:Number;
  public var rotation:Number;
}
class VelocityComponent
{
  public var velocityX:Number;
  public var velocityY:Number;
  public var angularVelocity:Number;
}
class DisplayComponent
{
  public var view:DisplayObject;
}
class Renderable implements IRenderable
{
  public var display:DisplayComponent;
  public var position:PositionComponent;
  public function render():void
  {
    display.view.x = position.x;
    display.view.y = position.y;
    display.view.rotation = position.rotation;
  }
}
class Moveable implements IMoveable
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;
  public function move( time:Number ):void
  {
    position.x += velocity.velocityX * time;
    position.y += velocity.velocityY * time;
    position.rotation += velocity.angularVelocity * time;
  }
}

When we create the spaceship we ensure the Moveable and Renderable instances share the same instance of the PositionComponent.

class Spaceship
{
  public function Spaceship()
  {
    moveData = new Moveable();
    renderData = new Renderable();
    moveData.position = new PositionComponent();
    moveData.velocity = new VelocityComponent();
    renderData.position = moveData.position;
    renderData.display = new DisplayComponent();
  }
}

The processes remain unaffected by this change.

A good place to pause

At this point we have a neat separation of tasks. The game loop cycles through the processes, calling the update method on each one. Each process contains a collection of objects that implement the interface it operates on, and will call the appropriate method of those objects. Those objects each do a single important task on their data. Through the system of components, those objects are able to share data and thus the combination of multiple processes can produce complex updates in the game entities, while keeping each process relatively simple.

This architecture is similar to a number of entity systems in game development. The architecture follows good object-oriented principles and it works. But there’s more to come, starting with a moment of madness.

Abandoning good object-oriented practice

The current architecture uses good object-oriented practices like encapsulation and single responsibility – the IRenderable and IMoveable implementations encapsulate the data and logic for single responsibilities in the updating of game entities every frame – and composition – the Spaceship entity is created by combining implementations of the IRenderable and IMoveable interfaces. Through the system of components we ensured that, where appropriate, data is shared between the different data classes of the entities.

The next step in this evolution of entity systems is somewhat counter-intuitive, breaking one of the core tenets of object-oriented programming. We break the encapsulation of the data and logic in the Renderable and Moveable implementations. Specifically, we remove the logic from these classes and place it in the processes instead.

So this

interface IRenderable
{
  function render();
}
class Renderable implements IRenderable
{
  public var display:DisplayComponent;
  public var position:PositionComponent;
  public function render():void
  {
    display.view.x = position.x;
    display.view.y = position.y;
    display.view.rotation = position.rotation;
  }
}
class RenderProcess implements IProcess
{
  private var targets:Vector.<IRenderable>;
  public function update( time:Number ):void
  {
    for each( var target:IRenderable in targets )
    {
      target.render();
    }
  }
}

Becomes this

class RenderData
{
  public var display:DisplayComponent;
  public var position:PositionComponent;
}
class RenderProcess implements IProcess
{
  private var targets:Vector.<RenderData>;
  public function update( time:Number ):void
  {
    for each( var target:RenderData in targets )
    {
      target.display.view.x = target.position.x;
      target.display.view.y = target.position.y;
      target.display.view.rotation = target.position.rotation;
    }
  }
}

And this

interface IMoveable
{
  function move( time:Number );
}
class Moveable implements IMoveable
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;
  public function move( time:Number ):void
  {
    position.x += velocity.velocityX * time;
    position.y += velocity.velocityY * time;
    position.rotation += velocity.angularVelocity * time;
  }
}
class MoveProcess implements IProcess
{
  private var targets:Vector.<IMoveable>;
  public function move( time:Number ):void
  {
    for each( var target:Moveable in targets )
    {
      target.move( time );
    }
  }
}

Becomes this

class MoveData
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;
}
class MoveProcess implements IProcess
{
  private var targets:Vector.<MoveData>;
  public function move( time:Number ):void
  {
    for each( var target:MoveData in targets )
    {
      target.position.x += target.velocity.velocityX * time;
      target.position.y += target.velocity.velocityY * time;
      target.position.rotation += target.velocity.angularVelocity * time;
    }
  }
}

It’s not immediately clear why we’d do this, but bear with me. On the surface, we’ve removed the need for the interface, and we’ve given the process something more important to do – rather than simply delegate its work to the IRenderable or IMoveable implementations, it does the work itself.

The first apparent consequence of this is that all entities must use the same rendering method, since the render code is now in the RenderProcess. But that’s not actually the case. We could, for example, have two processes, RenderMovieClip and RenderBitmap for example, and they could operate on different sets of entities. So we haven’t lost any flexibility.

What we gain is the ability to refactor our entities significantly to produce an architecture with clearer separation and simpler configuration. The refactoring starts with a question.

Do we need the data classes?

Currently, our entity

class Spaceship
{
  public var moveData:MoveData;
  public var renderData:RenderData;
}

Contains two data classes

class MoveData
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;
}
class RenderData
{
  public var display:DisplayComponent;
  public var position:PositionComponent;
}

These data classes in turn contain three components

class PositionComponent
{
  public var x:Number;
  public var y:Number;
  public var rotation:Number;
}
class VelocityComponent
{
  public var velocityX:Number;
  public var velocityY:Number;
  public var angularVelocity:Number;
}
class DisplayComponent
{
  public var view:DisplayObject;
}

And the data classes are used by the two processes

class MoveProcess implements IProcess
{
  private var targets:Vector.<MoveData>;
  public function move( time:Number ):void
  {
    for each( var target:MoveData in targets )
    {
      target.position.x += target.velocity.velocityX * time;
      target.position.y += target.velocity.velocityY * time;
      target.position.rotation += target.velocity.angularVelocity * time;
    }
  }
}
class RenderProcess implements IProcess
{
  private var targets:Vector.<RenderData>;
  public function update( time:Number ):void
  {
    for each( var target:RenderData in targets )
    {
      target.display.view.x = target.position.x;
      target.display.view.y = target.position.y;
      target.display.view.rotation = target.position.rotation;
    }
  }
}

But the entity shouldn’t care about the data classes. The components collectively contain the state of the entity. The data classes exist for the convenience of the processes. So we refactor the code so the spaceship entity contains the components rather than the data classes.

class Spaceship
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;
  public var display:DisplayComponent;
}
class PositionComponent
{
  public var x:Number;
  public var y:Number;
  public var rotation:Number;
}
class VelocityComponent
{
  public var velocityX:Number;
  public var velocityY:Number;
  public var angularVelocity:Number;
}
class DisplayComponent
{
  public var view:DisplayObject;
}

By removing the data classes, and using the constituent components instead to define the spaceship, we have removed any need for the spaceship entity to know what processes may act on it. The spaceship now contains the components that define its state. Any requirement to combine these components into other data classes for the processes is some other class’s responsibility.

Systems and Nodes

Some core code within the entity system framework (which we’ll get to in a minute) will dynamically create these data objects as they are required by the processes. In this reduced context, the data classes will be mere nodes in the collections (arrays, linked-lists, or otherwise, depending on the implementation) used by the processes. So to clarify this we’ll rename them as nodes.

class MoveNode
{
  public var position:PositionComponent;
  public var velocity:VelocityComponent;
}
class RenderNode
{
  public var display:DisplayComponent;
  public var position:PositionComponent;
}

The processes are unchanged, but in keeping with the more common naming I’ll also change their name and call them systems.

class MoveSystem implements ISystem
{
  private var targets:Vector.<MoveNode>;
  public function update( time:Number ):void
  {
    for each( var target:MoveNode in targets )
    {
      target.position.x += target.velocity.velocityX * time;
      target.position.y += target.velocity.velocityY * time;
      target.position.rotation += target.velocity.angularVelocity * time;
    }
  }
}
class RenderSystem implements ISystem
{
  private var targets:Vector.<RenderNode>;
  public function update( time:Number ):void
  {
    for each( var target:RenderNode in targets )
    {
      target.display.view.x = target.position.x;
      target.display.view.y = target.position.y;
      target.display.view.rotation = target.position.rotation;
    }
  }
}
interface ISystem
{
  function update( time:Number ):void;
}

And what is an entity?

One last change – there’s nothing special about the Spaceship class. It’s just a container for components. So we’ll just call it Entity and give it a collection of components. We’ll access those components based on their class type.

class Entity
{
  private var components : Dictionary;
  public function add( component:Object ):void
  {
    var componentClass : Class = component.constructor;
    components[ componentClass ] = component'
  }
  public function remove( componentClass:Class ):void
  {
    delete components[ componentClass ];
  }
  public function get( componentClass:Class ):Object
  {
    return components[ componentClass ];
  }
}

So we’ll create our spaceship like this

public function createSpaceship():void
{
  var spaceship:Entity = new Entity();
  var position:PositionComponent = new PositionComponent();
  position.x = Stage.stageWidth / 2;
  position.y = Stage.stageHeight / 2;
  position.rotation = 0;
  spaceship.add( position );
  var display:DisplayComponent = new DisplayComponent();
  display.view = new SpaceshipImage();
  spaceship.add( display );
  engine.add( spaceship );
}

The core Engine class

We mustn’t forget the system manager, formerly called the process manager.

class SystemManager
{
  private var systems:PrioritisedList;
  public function addSystem( system:ISystem, priority:int ):void
  {
    systems.add( system, priority );
    system.start();
  }
  public function update( time:Number ):void
  {
    for each( var system:ISystem in systemes )
    {
      system.update( time );
    }
  }
  public function removeSystem( system:ISystem ):void
  {
    system.end();
    systems.remove( system );
  }
}

This will be enhanced and will sit at the heart of our entity component system framework. We’ll add to it the functionality mentioned above to dynamically create nodes for the systems.

The entities only care about components, and the systems only care about nodes. So to complete the entity component system framework, we need code to watch the entities and, as they change, add and remove their components to the node collections used by the systems. Because this is the one bit of code that knows about both entities and systems, we might consider it central to the game. In Ash, I call this the Engine class, and it is an enhanced version of the system manager.

Every entity and every system is added to and removed from the Engine class when you start using it and stop using it. The Engine class keeps track of the components on the entities and creates and destroys nodes as necessary, adding those nodes to the node collections. The Engine class also provides a way for the systems to get the collections they require.

public class Engine
{
  private var entities:EntityList;
  private var systems:SystemList;
  private var nodeLists:Dictionary;
  public function addEntity( entity:Entity ):void
  {
    entities.add( entity );
    // create nodes from this entity's components and add them to node lists
    // also watch for later addition and removal of components from the entity so
    // you can adjust its derived nodes accordingly
  }
  public function removeEntity( entity:Entity ):void
  {
    // destroy nodes containing this entity's components
    // and remove them from the node lists
    entities.remove( entity );
  }
  public function addSystem( system:System, priority:int ):void
  {
    systems.add( system, priority );
    system.start();
  }
  public function removeSystem( system:System ):void
  {
    system.end();
    systems.remove( system );
  }
  public function getNodeList( nodeClass:Class ):NodeList
  {
    var nodes:NodeList = new NodeList();
    nodeLists[ nodeClass ] = nodes;
    // create the nodes from the current set of entities
    // and populate the node list
    return nodes;
  }
  public function update( time:Number ):void
  {
    for each( var system:ISystem in systemes )
    {
      system.update( time );
    }
  }
}

To see one implementation of this architecture, checkout the Ash entity system framework, and see the example Asteroids implementation there too.

A step further

In Actionscript, the Node and Entity classes are necessary for efficiently managing the Components and passing them to the Systems. But note that these classes are just glue, the game is defined in the Systems and the Components. The Entity class provides a means to find and manage the components for each entity and the Node classes provide a means to group components into collections for use in the Systems. In other languages and runtime environments it may be more efficient to manage this glue differently.

For example, in a large server-based game we might store the components in a database – they are just data after all – with each record (i.e. each component) having a field for the unique id of the entity it belongs to along with fields for the other component data. Then we pull the components for an entity directly from the database when needed, using the entity id to find it, and we create collections of data for the systems to operate on by doing joined queries across the appropriate databases. For example, for the move system we would pull records from the postion components table and the movement components table where entity ids match and a record exists in both tables (i.e. the entity has both a position and a movement component). In this instance the Entity and Node classes are not required and the only presence for the entity is the unique id that is used in the data tables.

Similarly, if you have control over the memory allocation for your game it is often more efficient to take a similar approach for local game code too, creating components in native arrays of data and looking-up the components for an entity based on an id. Some aspects of the game code become more complex and slower (e.g. finding the components for a specific entity) but others become much faster (e.g. iterating through the component data collections inside a system) because the data is efficiently laid out in memory to minimise cache misses and maximise speed.

The important elements of this architecture are the components and the systems. Everything else is configuration and glue. And note that components are data and systems are functions, so we don’t even need object oriented code to do this.

Conclusion

So, to summarise, entity component systems originate from a desire to simplify the game loop. From that comes an architecture of components, which represent the state of the game, and systems, which operate on the state of the game. Systems are updated every frame – this is the game loop. Components are combined into entities, and systems operate on the entities that have all the components they are interested in. The engine monitors the systems and the components and ensures each system has access to a collection of all the components it needs.

An entity component system framework like Ash provides the basic scaffolding and core management for this architecture, without providing any actual component or system classes. You create your game by creating the appropriate components and systems.

An entity component system game engine will provide many standard systems and components on top of the basic framework.

Three entity component system frameworks for Actionscript are my own AshEmber2 by Tom Davies and Xember by Alec McEachranArtemis is an entity system framework for Java, that has also been ported to C#.

My next post covers some of the reasons why I like using an entity system framework for my game development projects.

Share this post or a comment online –

Posted on 

Finite state machines are one of the staple constructs in game development. During the course of a game, game objects may pass through many states and managing those states effectively is important.

The difficulty with finite state machines in an entity system framework like Ash can be summed up in one sentence – the state pattern doesn’t work with an entity system framework. Entity system frameworks use a data-oriented paradigm in which game objects are not self-contained OOP objects. So you can’t use the state pattern, or any variation of it. All the data is in the components, all the logic is in the systems.

If your states are few and simple it is possible to use a good old fashioned switch statement inside a system, with the data for all the states in one or more components that are used by that system, but I wouldn’t usually recommend that.

When creating Stick Tennis I was faced with the problem of how to manage states as the two main entities in the game are the two players, and they go through a number of states as they…

  • prepare to serve
  • swing arm to toss the ball
  • release the ball
  • swing the racquet
  • hit the ball
  • follow through
  • run to a good position
  • react to the opponent hitting the ball
  • run to intercept the ball
  • swing the racquet
  • hit the ball
  • follow through
  • run to a good position
  • react to winning the point
  • …etc

Stick Tennis is a complex example, and I can’t show you the source code, so instead I’ll use something a little simpler, with source code.

An example

Lets consider a guard character in a game. This character patrols along a path, keeping watch. If they spot an enemy, they attack him/her.

In a traditional object-oriented state machine we might have a class for each state

public class PatrolState
{
    private var guard : Character;
    private var path : Vector.<Point>;
    public function PatrolState( guard : Character, path : Vector.<Point> )
    {
        this.guard = guard;
        this.path = path;
    }
    public function update( time : Number ) : void
    {
        moveAlongPath( time );
        var enemy : Character = lookForEnemies();
        if( enemy )
        {
            guard.changeState( new AttackState( guard, enemy ) );
        }
    }
}
public class AttackState
{
    private var guard : Character;
    private var enemy : Character;
    public function AttackState( guard : Character, enemy : Character )
    {
        this.guard = guard;
        this.enemy = enemy;
    }
    public function update( time : Number ) : void
    {
        guard.attack( enemy );
        if( enemy.isDead )
        {
            guard.changeState( new PatrolState( guard, PatrolPathFactory.getPath( guard.id ) );
        }
    }
}

In a entity system architecture we have to take a slightly different approach, but the core principle of the state pattern, to split the state machine across multiple classes, one for each state, can still be applied. To implement the state machine in an entity framework we will use one System per state.

public class PatrolSystem extends ListIteratingSystem
{
    public function PatrolSystem()
    {
        super( PatrolNode, updateNode );
    }
    private function updateNode( node : PatrolNode, time : Number ) : void
    {
        moveAlongPath( node );
        var enemy : Enemy = lookForEnemies( node );
        if( enemy )
        {
            node.entity.remove( Patrol );
            var attack : Attack = new Attack();
            attack.enemy = enemy;
            node.entity.add( attack );
        }
    }
}
public class AttackSystem extends ListIteratingSystem
{
    public function AttackSystem()
    {
        super( AttackNode, updateNode );
    }
    private function updateNode( node : PatrolNode, time : Number ) : void
    {
        attack( node.entity, node.attack.enemy );
        if( node.attack.enemy.get( Health ).energy == 0 )
        {
            node.entity.remove( Attack );
            var patrol : Patrol = new Patrol();
            patrol.path = PatrolPathFactory.getPath( node.entity.name );
            node.entity.add( patrol );
        }
    }
}

The guard will be processed by the PatrolSystem if he has a Patrol component, and he will be processed by the AttackSystem if he has an Attack component. By adding/removing these components from the guard we change his state.

The components and nodes look like this…

public class Patrol
{
    public var path : Vector.<Point>;
}
public class Attack
{
    public var enemy : Entity;
}
public class Position
{
    public var point : Point;
}
public class Health
{
    public var energy : Number;
}
public class PatrolNode extends Node
{
    public var patrol : Patrol;
    public var position : Position;
}
public class AttackNode extends Node
{
    public var attack : Attack;
}

So, by changing the components of the entity, we change the entities state and thus change the systems that process the entity.

Another example

Here’s another, more complex example using the Asteroids example game that I use to illustrate how Ash works. I’ve add an additional state to the spaceship for when it’s shot. Rather than simply removing the spaceship when it is shot, I show a short animation of it breaking up. While doing this, the user won’t be able to move it and the spaceship won’t react to collisions with other objects.

The two states require the following

While the ship is alive –

  • It looks like a spaceship
  • The user can move it
  • The user can fire its gun
  • It collides with asteroids

When the ship is dead –

  • It looks like bits of a spaceship floating in space
  • The user cannot move it
  • The user cannot fire its gun
  • It doesn’t collide with asteroids
  • After a fixed time it is removed from the game

The relevant piece of code, where the spaceship dies, is in the CollisionSystem. Without the second state it would look like this

for ( spaceship = spaceships.head; spaceship; spaceship = spaceship.next )
{
    for ( asteroid = asteroids.head; asteroid; asteroid = asteroid.next )
    {
        if ( Point.distance( asteroid.position.position, spaceship.position.position )
            <= asteroid.position.collisionRadius + spaceship.position.collisionRadius )
        {
            creator.destroyEntity( spaceship.entity );
            break;
        }
    }
}

The code tests whether the ship is colliding with an asteroid, and if it is it removes the ship. Elsewhere, the GameManager system handles the situation where there is no spaceship and creates another one, if any are left, or ends the game. Instead of destroying the spaceship, we need to change its state. So, lets try this…

We can prevent the user controlling the spaceship by simply removing the MotionControls and GunControlscomponents. We might as well remove the Motion and Gun components while we’re at it since they’re of no use without the controls. So we replace the code above with

for ( spaceship = spaceships.head; spaceship; spaceship = spaceship.next )
{
    for ( asteroid = asteroids.head; asteroid; asteroid = asteroid.next )
    {
        if ( Point.distance( asteroid.position.position, spaceship.position.position )
            <= asteroid.position.collisionRadius + spaceship.position.collisionRadius )
        {
            spaceship.entity.remove( MotionControls );
            spaceship.entity.remove( Motion );
            spaceship.entity.remove( GunControls );
            spaceship.entity.remove( Gun );
            break;
        }
    }
}

Next, we need to change how the ship looks and remove the collision behaviour

for ( spaceship = spaceships.head; spaceship; spaceship = spaceship.next )
{
    for ( asteroid = asteroids.head; asteroid; asteroid = asteroid.next )
    {
        if ( Point.distance( asteroid.position.position, spaceship.position.position )
            <= asteroid.position.collisionRadius + spaceship.position.collisionRadius )
        {
            spaceship.entity.remove( MotionControls );
            spaceship.entity.remove( Motion );
            spaceship.entity.remove( GunControls );
            spaceship.entity.remove( Gun );
            spaceship.entity.remove( Collision );
            spaceship.entity.remove( Display );
            spaceship.entity.add( new Display( new SpaceshipDeathView() ) );
            break;
        }
    }
}

And finally, we need to ensure that the spaceship is removed after a short period of time. To do this, we’ll need a new system and component like this

public class DeathThroes
{
    public var countdown : Number;
    public function DeathThroes( duration : Number )
    {
        countdown = duration;
    }
}
public class DeathThroesNode extends Node
{
    public var death : DeathThroes;
}
public class DeathThroesSystem extends ListIteratingSystem
{
    private var creator : EntityCreator;
    public function DeathThroesSystem( creator : EntityCreator )
    {
        super( DeathThroesNode, updateNode );
        this.creator = creator;
    }
    private function updateNode( node : DeathThroesNode, time : Number ) : void
    {
        node.death.countdown -= time;
        if ( node.death.countdown <= 0 )
        {
            creator.destroyEntity( node.entity );
        }
    }
}

We add the DeathThroesSystem to the game at the start, so it will handle the drawn-out death of any entity. Then we add the DeathThroes component to the spaceship when it dies.

for ( spaceship = spaceships.head; spaceship; spaceship = spaceship.next )
{
    for ( asteroid = asteroids.head; asteroid; asteroid = asteroid.next )
    {
        if ( Point.distance( asteroid.position.position, spaceship.position.position )
            <= asteroid.position.collisionRadius + spaceship.position.collisionRadius )
        {
            spaceship.entity.remove( MotionControls );
            spaceship.entity.remove( Motion );
            spaceship.entity.remove( GunControls );
            spaceship.entity.remove( Gun );
            spaceship.entity.remove( Collision );
            spaceship.entity.remove( Display );
            spaceship.entity.add( new Display( new SpaceshiopDeathView() ) );
            spaceship.entity.add( new DeathThroes( 5 ) );
            break;
        }
    }
}

And that is our state transition. The transition is achieved by altering which components the entity has.

The state is encapsulated in its components

This is the general rule of the entity system architecture – the state of an entity is encapsulated in its components. If you want to change how an entity is processed, you should change its components. That will alter which systems operate on it and that changes how the entity is processed.

Standardised state machine code

To help with state machines I’ve added some standard state machine classes to Ash. These classes help you manage states by defining states based on the components they contain, and then changing state simply by specifying the new state you want.

A finite state machine is an instance of the EntityStateMachine class. You pass it a reference to the entity it will manage when constructing it. You will usually store the state machine in a component on the entity so it can be recovered from within any system that is operating on the entity.

var stateMachine : EntityStateMachine = new EntityStateMachine( guard );

A state machine is configured with states, and the state can be changed by calling the state machine’s changeState() method. States are identified by a string, which is assigned when the state is created and used to identify the state when calling the changeState() method.

States are instances of the EntityState class. They may be added to the EntityStateMachine using the EntityStateMachine.addState() method, or they may be created and added in one call using the EntityStateMachine.createState() method.

var patrolState : EntityState = stateMachine.createState( "patrol" );
var attackState : EntityState = stateMachine.createState( "attack" );

A state is a set of components that should be added to the entity when that state is entered, and removed when that state exits (unless they are also required for the next state). The add method of the EntityState specifies the type of component required for the state and is followed by a rule specifying how to create that component.

var patrol : Patrol = new Patrol();
patrol.path = PatrolPathFactory.getPath( node.entity.name );
patrolState.add( Patrol ).withInstance( patrol );
attackState.add( Attack );

The four standard rules for components are

entityState.add( type : Class );

Without a rule, the state machine will create a new instance of the given type to provide the component every time the state is entered.

entityState.add( type : Class ).withType( otherType : Class );

This rule will create a new instance of the otherType every time the state is entered. otherType should be the same as or extend the specified component type. You only need this rule if you create component classes that extend other component classes and should be treated as the base class by the engine, which is rare.

entityState.add( type : Class ).withInstance( instance : * );

This method will use the provided instance for the component every time the state is entered.

Finally

entityState.add( type : Class ).withSingleton();

or

entityState.add( type : Class ).withSingleton( otherType : Class );

will create a single instance and use that one instance every time the state is entered. This is similar to using the withInstance method, but the withSingleton method will not create the instance until it is needed. If otherType is omitted, then the singleton with be an instance of type, if included it will be of otherType and otherType must be the same as or extend type.

Finally, you can use custom code to provide the component by implementing the IComponentProvider interface and then using your custom provider with

entityState.add( type : Class ).withProvider( provider : IComponentProvider );

The IComponentProvider interface is defined as

public interface IComponentProvider
{
    function getComponent() : *;
    function get identifier() : *;
}

The getComponent method returns a component instance. The identifier in the IComponentProvider is used to compare two component providers to see if they will effectively return the same component. This is used to avoid replacing a component unnecessarily if two successive states use the same component.

The methods are designed to be chained together, to create a fluid interface, as you’ll see in the next example.

Back to the examples

If we apply these new tools to the spaceship example, the states are set-up when the spaceship entity is created, as follows

var fsm : EntityStateMachine = new EntityStateMachine( spaceshipEntity );
fsm.createState( "playing" )
   .add( Motion ).withInstance( new Motion( 0, 0, 0, 15 ) )
   .add( MotionControls )
       .withInstance( new MotionControls( Keyboard.LEFT, Keyboard.RIGHT, Keyboard.UP, 100, 3 ) )
   .add( Gun ).withInstance( new Gun( 8, 0, 0.3, 2 ) )
   .add( GunControls ).withInstance( new GunControls( Keyboard.SPACE ) )
   .add( Collision ).withInstance( new Collision( 9 ) )
   .add( Display ).withInstance( new Display( new SpaceshipView() ) );
fsm.createState( "destroyed" )
   .add( DeathThroes ).withInstance( new DeathThroes( 5 ) )
   .add( Display ).withInstance( new Display( new SpaceshipDeathView() ) );
var spaceshipComponent : Spaceship = new Spaceship();
spaceshipComponent.fsm = fsm;
spaceshipEntity.add( spaceshipComponent );
fsm.changeState( "playing" );

and the state change is simplified to

for ( spaceship = spaceships.head; spaceship; spaceship = spaceship.next )
{
    for ( asteroid = asteroids.head; asteroid; asteroid = asteroid.next )
    {
        if ( Point.distance( asteroid.position.position, spaceship.position.position )
            <= asteroid.position.collisionRadius + spaceship.position.collisionRadius )
        {
            spaceship.spaceship.fsm.changeState( "destroyed" );
            break;
        }
    }
}

To do

There will be further refinement and additions to the state machine tools based on feedback so please do let me know how you get on with them. Use the mailing list for Ash to get in touch.

Share this post or a comment online –