Posted July 25, 2025 by sirdorius
So using ECS is pretty straightforward for real time games, as long as you don’t mess up the execution order of systems too much. But how do you model turn based games using ECS?
The code snippets below are written using Friflo.ECS, a C# library, but most of the concepts easily apply to others, like Flecs, or Bevy. I embedded code as images not because I hate my readers, but because Itch code formatting is nonexistent, which makes it unreadable. The full code is available here.
In my first attempt I was following the tutorial pretty closely: saving actions to a queue, then dequeing and executing them in FIFO order using a polymorphic Execute method on each action and passing it an entire mutable world. This was not using basically any ECS features at all and I didn’t like the “here’s a mutable world, do whatever” approach, so I wanted to try a more “idiomatic” ECS approach to see if there were any advantages.
For my refactoring I divided everything into 2 phases that are run in sequence every tick:
UpdatePhases.ProgressTurns.Add(new TickEnergySystem());
UpdatePhases.ApplyActions.Add(new ProcessActionsSystem());
Let’s see them in detail.
The first phase (ProgressTurns) is responsible for finding the next character who should act (via the TickEnergySystem) and then producing one or more actions for that character using a bunch of other systems.
I implemented the energy system described in Bob’s article where characters each recharge their turns separately and one character can take multiple turns while another recharges. Each character entity has an Energy component that tracks these values:
struct Energy() : IComponent {
int Current = 0;
required int GainPerTick;
int AmountToAct = 10;
}
Once a character has enough energy to act, a self explaining CanAct tag is added to its entity by TickEnergySystem. Queries are cached in normal code, but more explicit in the examples to see what data they are operating on.
Once a character can act, multiple systems can pick it up and create actions for it, for example a system to randomly move entities that have a GridPosition component and the tags Enemy && CanAct
TurnsManagement.QueueAction() is just creating a new entity with a MovementAction component and the IsActionWaiting and optional IsActionBlocking tags that we will see soon. This is basically using ECS to create a queue of actions to be executed, rather than the typical list in the previous implementation.
During the ApplyActions phase we take queued actions and resolve them. Actions are any kind of component with one or more of the following tags:
The following system does some maintenance on current actions and prepares new ones for execution:
And then systems can query for specific actions and execute them. For example a movement action:
Is it all a bit overengineered for the sake of idiomatic ECS? Probably, yes. Compared to the simple, no ECS method (provided in the beginning) these are the things I can think of:
Advantages:
Disadvantages:
Some notes on other ECSs: