What is an entity system framework for game development?

Last week I released Ash, an entity system framework for Actionscript game development, and a number of people have asked me the question “What is an entity 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.

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 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 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.

Conclusion

So, to summarise, entity systems originate from a desire to simplify the game loop. From that comes an architecture of entities, 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. Entities are made up of components, and systems operate on the entities that have the components they are interested in. The engine monitors the systems and the entities and ensures each system has access to a collection of all the entities that have the appropriate components.

However, systems don’t generally care about the entity as a whole, just the specific components they require. So, to optimise the architecture and provide additional clarity, the systems operate on statically typed node objects that contain the appropriate components, where those components all belong to the same entity.

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

An entity based game engine will provide many standard systems and entities on top of the basic framework.

Three entity 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.

99 thoughts on “What is an entity system framework for game development?

  1. @David: IMHO to make something invisible means to make it not renderable. So you just need to remove RenderSystem from such entity. That rather should not be a part of your framework in general, that’s some functionality of concrete game. Alternatively, what about extending RendererSystem and adding some code to render ‘invisible’ entity?

    @Richard: Excellent post :) . But there’s one thing that is bothering me. It’s the usage of “Component” term. As for me, structures that contains some data only should be rather named as value objects/models. Even in PushButton engine, “Component” means something more than bare data structure (i.e. HeroControllerComponent could manage keyboard input and change position/angle stored inside this component). Not to mention, what “Component” means in UI programming (it’s rather mix of view, model and controller layers). I’m not as experienced programmer as you, so I’m asking – what are roots of this “Component” term?

  2. @Maciek: I use the term component because it is a common term in this context within entity systems. The origins are the component as a constituent part of the entity – i.e. the general english language meaning of a component as a constituent part of something.

    I agree that there is potential for confusion within software development and had I invented the whole entity architecture I’d have been inclined to use a different term, like Ingredient or Element. But given the term is now a standard within entity systems it makes sense to use it in Ash.

  3. @David: As Maciek says, you either make visibility a feature of renderable objects and so add a visible property to the render component, or you remove the render component from the entity to prevent rendering it.

    There is one other option, but I would not recommend it in your example, and that is within the render system to test whether the entity has an invisible component (in Ash this would be node.entity.has( Invisible ) ).

  4. But the players should have the ability to go invisible. Invisibility should be coordinated across a server/client, and thus should be seperate from the RenderSystem. Maybe the RenderNode should have an optional parameter?

    Speaking of which, how would I go about networking entities? Should each component have a networkable flag? Tweening may become an issue as well.

  5. I am very curious how to add to such architecture something like Tweener? I can imagine some solutions but all of them make it less comfortable in use than traditional way.

  6. Pingback: Games And Entity Systems | Shaun Smith

  7. Pingback: Aymeric Lamboley » An entity/component system’s attempt using Box2D

  8. hi,it’s a good framework,but not easy to use.there are so many properties should be set in code.if you make a tool,can translate a xml to a game with your famework,it will be better.

  9. Pingback: Box Hacker » Blog Archive » Using an entity component system in AS3

  10. Pingback: Entity Systems | Tom Davies

  11. Pingback: Game Architecture | Tom Davies

  12. Pingback: Von OOP zu MVC - Flashforum

  13. Pingback: The Problem of Identity | RedIrony

  14. Pingback: Useful Links « Paige Ashlynn

  15. I have two versions of getComponent function, one check for inexistent components (used by systems that can act in a variety of entities even if not all have the same component set, like AI), the other, the fast one, allow memory violation if you try to access an inexistent component. System that access components this way, have an interface to get notified when an entity changes its component set (removal or addition of components) and then recheck the entity and if it has no more the required components by that system the entity get removed from the system, but these systems never check for components during game loop, because that would make them run slow.

  16. I am trying using starling tween for animating some of the entities and I am able to find the best way to integrate tween with rendering and animating system as used in Asteroids example. So the scenarios is,

    - There is an Inputsystem which handles all inputs and delegates to input nodes.
    - Input nodes depending on the input will perform some action like move to the clicked point, change state or animate.

    Any help on how to integrate the animation/tween with ASH will be really helpful

  17. Some documentation explaining how “families” work would be very useful, I am unable to glean from the code how exactly systems gain reference to an entity’s relevant node when added/created.

  18. An Entity contains a dictionary of Components.
    A Node contains references to an Entity’s relevant components.
    A System works on Nodes.
    The Engine contains the Entities and the Systems.

    In the Asteroids example:
    You create the Engine and add the needed Systems.
    You create the Entities with needed Components, and add them to Engine. Then….?

    I can’t find where in the code the Entities’ nodes are created and passed on to the Systems. The unmentioned ComponentMatchingFamily class does something like this, but it doesn’t communicate with any System.

    Also, since one needs to check an Entity’s components before creating/adding the node to a System…. Why bother using Nodes? Couldn’t the Systems keep references of the Entity’s needed components instead of using Nodes to do exactly that?

    One final question, the limited info on entity systems seem to suggest that in a c# environment the components would be structs (which don’t exist in java) and not classes as in the c# version of Ash, is that correct?

    -Thank you

  19. Pingback: Tinkering With Ash - MikeCann.co.uk - mikey see, mikey do!

  20. Pingback: Entity Component Systems | Chad Miller's Software Blog

  21. Hi, thanks for this article, it is very inspiring.

    I have the feeling I tried to picture this for a long time, but things has always been blurry and unclear.

    Now it is crystal clear thanks to your explanations. I tried to implement this in C#, lurking the core Ash action script source code at the same time. It was not easy because I do not know ActionScript at all, so I struggle to understand really how nodes and components reacts each other.

    Now I have something that works: a very simple application with a thin core engine that respect this architecture and makes some balls bouncing everywhere using Farseer Physics Engine and WPF.

    As it has opened a door to me, I will try to make something more interresting in the future.

  22. Pingback: Entity Component Systems - A Practical Example | wasted potential

  23. Richard, excellent article. This is probably the best article on ECS I’ve seen to date. However, there is one thing that has me puzzled. In the article, you remove the Data Classes (RenderData, MoveData), to have the components in the entities themselves. That I understood. But then you reintroduce the Data Classes as Nodes (Why? I thought they went away.), then kinda gloss over Nodes’ implementation in the detail you gave everything else. Could you expand on the Nodes and why and how you use them?

  24. @Da Gamer

    Before removing the data classes the entity was composed of the data classes and the data classes were composed of components. I remove the data classes because they are not needed for the entities – the entities can and should be composed of the components themselves.

    However, the data classes are also the aggregating object that combines components for use by the systems. This requirement is still present, sort of, which is why they are reintroduced as nodes, but only for use by the systems, they are no longer part of the entities.

    We could not reintroduce the nodes and instead provide each system directly with a collection of entities that have all the necessary components for that system, and the system could fetch each component from each entity as required. But all the component look-ups and casting would be much slower than using the nodes. It can be made a lot faster with a language that supports generics but ultimately the nodes are just more efficient and they simplify the systems since everything in the node is statically typed.

  25. @Kyle I left out the implementations of the start() and end() methods in the classes that implement ISystem since they are irrelevant to the discussion.

  26. I keep rereading this and several other articles on this subject, but always come away with the same questions. The 1st is related to this part:

    “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.”

    Can you explain how this would work? From your diagram, it looks like systems only operate on nodes, which are essentially wrappers around components. But the way you described the case above makes it sound like systems are operating on entities, and indeed, they would need to be in order for one (render) system to ignore a collection of components that should be handled (rendered) by a different (render) system. Or is there some other design trick to get this to work where a system only operates on components?

  27. Hi Tim

    Systems operate on the components that make up the entities. As such they indirectly operate on the entities. But you’re right that all they know or care about are the nodes, which are just a collection mechanism for the components.

    How we render different entities in different ways is in fact very simple, we use different components. If one entity has a BitmapComponent and another has a MovieClipComponent, and we have two render systems, one that handles BitmapComponents and one that handles MovieClipComponents, then the two entities will be rendered by different systems.

  28. Pingback: Considering Entity-Component systems | bhopkins.net

  29. Pingback: Entity driven Scene Manager | Introvert Studios Development Blog

  30. Pingback: Entity Component System?C++???????? | necoco

  31. Pingback: Entity component system : Component tips | Box Hacker

  32. First of all, thank you for your great articles on Entity Systems and the Ash framework!

    I have studied the Asteroids example in the Ash framework and wanted to add something simple to the game to test my understanding of the Entity System approach.

    I thought giving the ability of the Asteroids to fire back at the spaceship would be a good test. This should demonstrate how easy it is to take existing components and expand the capabilities of an Entity.

    My goal was to have the Asteroids fire a bullet at a set interval in the direction dictated by the Asteroids current rotation. I also needed to add logic to detect collisions with the bullets to the Spaceship (and not with other Asteroids). I ended up adding several new systems and nodes to make this happen:

    New Components:
    AsteroidBullet – Bullet from an asteroid
    AutoGun – Auto firing gun

    New Nodes:
    AsteroidBulletAgeNode
    AsteroidBulletCollisionNode
    AutoGunControlNode

    New Systems:
    AsteroidBulletAgeSystem
    AutoGunControlSystem

    I modified CollisionSystem to look for collisions between AsteroidBullets and the Spaceship, modified the CreateAsteroid method to add in the AutoGun component, and added a new CreateAsteroidBullet method.

    Does this seem like a reasonable approach? Should I have added more logic to existing systems to account for the different behavior of the auto firing gun and asteroid bullets instead of creating new components and systems?

  33. Have read this twice now and still don’t understand this:
    1. Spaceship is Renderable and Moveable at first. By saying that they have RenderData and MoveData, which are 1-to-1 with rendering/moving, and so we know that the spaceship can move and render because it owns these very specific objects.
    2. As we remove the MoveData and RenderData, we still have the data the rendering/movement needs, but nowhere we can know that the spaceship actually *should* render, move or both.

    So the question is.. how do we know/define that the spaceship should move and/or render in your final example?

  34. Pingback: C++:Implementing "ash" Entity framework | Stackforum

  35. Pingback: Reference Links | Coffee, Code and Fractals

  36. Pingback: Entity Systems in C++CopyQuery CopyQuery | Question & Answer Tool for your Technical Queries,CopyQuery, ejjuit, query, copyquery, copyquery.com, android doubt, ios question, sql query, sqlite query, nodejsquery, dns query, update query, insert query,

  37. Hi,

    I’m not a game designer, but I saw this on Hacker News and it was extremely interesting. Thanks for posting.

    I’d like to double-check that I’ve understood what’s going on. In your system, Entities are completely dynamic: to make an entity behave in a certain way, you just provide it with the appropriate Components, and the Engine takes care of the rest. So to make an object that can move, you just give it a PositionComponent and a VelocityComponent. The Engine notices what you’ve done, creates a MoveNode, and passes the MoveNode to the MoveSystem.

    Is that right?

  38. Pingback: Gene Ontology and Object Oriented Programming | Arun Durvasula

  39. Pingback: Using GameLoop in Your Own C++ Projects |

  40. Great article! I’m trying to implement my first game using this approach so, thank you very much =)

    I do have a question though, who is responsible to create the nodes? AFAIU, you create an entity, then add it to the Engine who should create the nodes given the components present on the entity. I.e:

    Given my entity has components A, B and D, and
    there is the node types NodeAB, NodeBD and NodeABC

    When I add a new entity to the Engine, the Engine creates (or asks for someone else to create) an instance of a NodeAB, an instance of NodeBD but no instances of NodeABC

    Is that correct?

  41. Pingback: ES Tutorials - Entity Systems Wiki

  42. Thank you for this excellent article! Got inspired by this and wrote my own simple EC system in Lua. Works nicely!

    A quick question about events and “entity communication”: I haven’t looked at your source code, but how do you implement communication between different entities?

    My simple solution has been to pass an event from the system to the engine, with the entity ID and the event args. For instance, if the collision detection system detects a collision for an entity, the collision system sends a message to the engine, which in turn sends a message to all systems that process this entity (I keep a list of systems associated to each entity ID to make this faster). It’s then up to the individual systems to respond to the events that they are interested in. For instance, my enemy AI system responds to a collision by negating the velocity vector.

    Does this sound reasonable, or is there another way of doing things, that is more “standard”?

  43. I’m a little late to the frey, but _thanks_ for this great article!

    I recently invented CES in exactly the way you described. Almost! I had written a game (Super Plumber Bros) with some friends. The main loop was a deeply nested mess of callbacks and control statements, and I thought “huh, all of this seems to just be managing state.”

    In my next project, I implemented an FSM to replace the main loop. Now, in this more recent project (Darkest Path, coming in August), the load function sets up a state machine: each state has an update method, and these update methods mainly coordinate which objects do what, and when. On the title screen, key input is collected and the title screen is rendered. When the game starts, the map and player will be drawn, but not the title screen. The load function, where all the states and transitions are declared, was just as long as in SPB but was much less complex and much easier to extend. However, looking at it made me think “huh, in each state… different systems run. Why not just declare which systems run in which states?”

    Which brings me to my most recent project! The load function sets up an FSM, adding states and transitions, but the states just look like, for example, this:

    fsm.addState({ name = “run”, systems = { “render”, “physics”, “collision” })

    In every state, a list of systems (indexed by strings) are run. They are responsible for plunging into the game’s data (which you call “Entities”) and getting the stuff they need. The data is yet another table, and the systems know how to query the table.

    What I’ve taken away from your article, aside from a sense that “I’m not alone”, is the Engine and the “Nodes”. My FSM coordinates the systems very well, but the way that the systems query the entity table is neither clean nor efficient. Much nicer if there is an intermediary class like you Engine to register and collect the data for each system!

    So yeah, this is great!

  44. Pingback: ??????ECS?????? » CHU????

  45. Pingback: Ashley entity framework | David Saltares

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>