Game Programming

ECS Concepts – Part 4: Systems Overview

by Cory on October 17, 2017 12:38 AM

Damn, it’s been a little while. I was trying to hold off on writing this post until I fleshed out a few systems in my code before starting the systems section in case there were some big changes I needed to make. Instead of doing that, I was uh… reading books and watching TV. I started working on making an input handling system a few days ago and it looks like there won’t be any big changes, mostly some additions to the existing code. More on that later.

I’m going to have a couple of different articles to cover systems related stuff because it’s really big compared to the things I’ve talked about so far. In this post, I’ll give a high level overview of all the big parts that make up my System class and then in the next couple of posts, I’ll give more detailed info about each piece below.

Systems Do 2 Things

So once again, in essence, a system is the piece of the ECS framework where all the business logic happens. A game has many systems working in parallel to handle everything from physics to health, player control, and drawing. A System should (1) update roughly once per game loop iteration and (2) go through all the entities it cares about and do stuff with data in the entities’ components.

I think I’ve described examples of systems already, but here’s one more.A simple example might be a physics system that loops through all entities in your “world” that have both Position and Velocity components and updates each entity’s position based on the values in the Velocity component on every iteration of the game loop. The intended usage by clients should be to inherit from a base System class and implement their own functionality in the init() and update() methods. When a System is created, the init() method is called and things that need to be set up at the very beginning are put in that function. The update() method contains all the logic I just described in the previous example.

Ok, so (1) seems pretty straightforward right? (It might not be, see “Updating Systems” below…) So let’s take a look at (2) for now. The main concern here is to figure out which entities a system is interested in. How does that happen?

Entity Filtering

I am gonna call it “entity filtering”. Systems need to be able to take an entity and figure out whether or not it is interested in the aforementioned entity based on what kinds of components it has. A naive solution isn’t that complicated. You could define a pure virtual method like bool filter(Entity* e) that requires the implementer to take the supplied entity and calculate the return value based on which components it has. (Well, at least you better hope the implementer knows this. Maybe make some really flashy comments or something?)

A less half-ass solution is more complicated under the hood, but makes the whole process way more user friendly and has nice syntax.This is what the next post is about. It’s gonna be awesome, trust me.

Entity Subscription Lists

Once the entity filter is working, a good idea would be to have systems keep track of all the entities that have made it through the filter for performance reasons. This list of entity references is stored in the system and it’s what I call an “entity subscription”. Entity subscriptions are an optimization, but I’m thinking it’s most likely necessary because I think having every single system iterate through every single entity every single frame has a good chance of being a performance bottleneck for even the simplest things. This does make adding new entities, modifying entity components, and removing entities a little more complicated, however. Hopefully we can take care of that with some new tools I’ll introduce later. (If you are from the future and you’ve come back here to read this part again, I’m talking about making messages to tell systems to modify their subscription lists whenever these events happen.)

This was a pain in the ass to figure out, btw. I spent a lot of days of my vacation just sitting and staring at the wall and rewriting stuff. And the end result wasn’t even that much code... I wanted to have a few different implementations of an entity subscription list for different applications. For instance, you’ve probably already guessed that the base implementation stores everything in a flat array and just iterates over it during a system update. Basically for a base subscription we don’t really care what order the entities are updated by the system. But there’s other cases, like for a system that draws graphics to a screen, where I want to iterate in very specific order. In a graphical system, I’d want to iterate over entities based on where they are in the scene graph. Leaf nodes of the scene graph should be drawn last, so they end up on top of their parent nodes (I do a pre-order traversal). How do I do that? Oooooh I dunno magic.

Initializing Systems

I gave each system an initialization method that will be called once upon creation (but before the first update is called). The first thing that people should do when making a new system is to configure the entity filter in here. More specifically, you provide the system with a simple boolean expression of Component class types that you would like the system to evaluate when filtering entities.

The init() method is also for things that must be done once at the beginning but cannot go in the constructor. I haven’t made enough systems to run into any use cases for this so who knows. I’ll fill you in later if I find any.

Updating Systems

The meat of a system. This is automatically run every iteration of the game loop. My base class automatically iterates through all the entities in the subscriber list and calls update for every entity in the list. This part is most subject to change I think, because of 3 things:

  1. Updates to my game time step function. Right now I have my game blindly updating once every sixtieth of a second. I mean, that’s normal, but there’s a lot that goes into it. A lot of engines move away from updating at a constant 60 fps to prevent game logic from being inadvertently tied to the framerate. In other words, you might experience lag or stuttering if the framerate falls below 60 fps or maybe the game will run super fast if you have a strong processor and the framerate goes above 60 fps. Modern solutions can remedy this by changing to a variable timestep based on the computational power of the computer. And even more modern solutions can make the graphics smoother by adding frame interpolation. This may affect the system update code in ways that I’m not sure of right now...

  2. Having certain systems needing to update multiple entities at the same time. I don’t really know how I’m going to handle this yet, especially because I haven’t yet needed to do anything that needed this. What if, for instance, you were doing a collision detecting system or something and needed to compare every entity with every other entity? Then having 2 entities supplied to this function might make sense. Or not? On the other hand, it might stay the way it is.

  3. I might want to add an option to create systems that update every n frames or so instead of every single frame. I haven’t had to do this yet, but the Artemis ODB documentation reveals that they have a variant of the System class that does this. Maybe for systems that cull unused entities?


I’ll probably end up writing another whole thing about the game loop time step, but that’s later. That whole business seems complicated. Here’s a link about game engine time steps if you’re interested.


This is another huge topic. Messaging is not just confined to systems but they will rely on messaging a lot, so I’ll lump it in here. Each system (or anything that should be able to send and receive messages) needs to have a Mailbox module. These mailboxes need to be hooked up to each other somehow as well. Then once you’ve done that, you can send messages (classes that inherit from Message) of any kind containing the relevant data. A loooot of super cool code went into this.

System Code Outline

class System {
// enable/disable suppresses calls to update()
void enable();
void disable();
bool is_enabled();

void init(Game& game);
void update(Game& game);

// messaging interface
template <
typename MsgT,
typename std::enable_if<std::is_base_of<Message, MsgT>::value>::type* = nullptr
void receive_message(std::shared_ptr<MsgT> message);

template <
typename MsgT,
typename std::enable_if<std::is_base_of<Message, MsgT>::value>::type* = nullptr
void send_message(Args&&... args);

template <
typename MsgT,
typename std::enable_if<std::is_base_of<Message, MsgT>::value>::type* = nullptr
void send_message_async(Args&&... args);

World* world_;
Mailbox mailbox_;
EntitySubscription* subscription_; // entity filter is inside

virtual void on_init(Game& game) = 0;
virtual void on_update(Game& game, Entity& entity) = 0;

NOTE: if you take a look at the System class (/engine/ECS/System) in my git repo, you’ll notice a bunch of little changes, including the fact that World is actually named Scene. I’m planning on changing the name in new iterations, but for now it’s stuck with the old name. Just clarifying.

I’ve omitted the implementation of the send/receive message functions for now, because those belong in the messaging article. But you might be able to glean some interesting things about how it works just from the function headers.

For the init() and update() functions, I use the non-virtual interface (NVI) design pattern. This is the one where the base class has non-virtual functions that are part of the public interface. Within those non-virtual functions, the base class is free to call private, virtual functions (I call them “hooks”) in any way it sees fit. The private part is important; almost all the time, you probably want your hooks to be only accessible by children classes. When a client inherits from the base class, it must implement the virtual function hook. Of course, this hook implementation still has to follow the implicit contract that the base class lays down.

In this case, there is no contract. For init(), it is recommended to set up the entity filter (or else by default the filter won’t allow anything and the system won’t process any entities). The user is free to stuff whatever else into the init() function since the hook does not return anything.

Here’s how the initialization hook is done. Note that in System::init(), all child systems get these actions done for free:

void System::init(Game& game) {
// keep reference to world; assume world never changes per system
assert(this->world_ == nullptr);
this->world_ = game.current_scene();

// here is the init hook I mentioned above

// initialize entity filter and entity subscription

The update function is a little more complex. It iterates through the subscriber list and calls the update hook with a reference to each entity. From the point of view of a child system calling the on_update() function, it only sees that it is magically provided with the right entities.

void System::update(Game& game) {
if (!this->is_enabled()) {

assert(this->world_ != nullptr); // that would be bad!

// handle any queued up messages

std::function<void(Handle)> handle_on_update = [&](Handle h) {
Entity* e = this->world_->get_entity(h);
if (e) {
this->on_update(game, *e);
this->subscription_->for_each(*this, handle_on_update);

I’m pretty sure I’m going to have to modify the on_update hook to supply it the entity’s handle too. There’s currently no way to get the handle if you just have the entity pointer (the idea is that the handle may change frequently and you want to touch the pointer for the shortest time possible).

Integration of ECS Classes into the Scene

This will be yet another post. I didn’t talk about it yet, but the class that contains the whole ECS setup is closely integrated in my design. Imagine that there’s this class called World that contains all the systems and entities and stuff. There needs to be code to let the user add/remove/manage systems, send messages between all of them and manage what happens to entities as well. This class is analogous to “Scene” in libgdx or Unity. I’ll probably dedicate another post to just talking about the integration necessary.

So there. Stay tuned, the next few posts are gonna contain a lot of interesting code!

This Thought is part of Game Programming

Game programming general topic. I eventually hope to split this into separate ideas exclusively about specific games that I make.

back to the