Skip to content
Lesson 6 of 14

Step 1 of 5 · Reading · ~3 min

Read

Entity-Component System

Systems & Schedules

A system is a function that runs once per frame over every entity that has some set of components. An engine has dozens of them, and the order they run in decides what the player sees. After this lesson your program will take a list of systems, each declaring what it reads and writes, and produce a schedule that runs the safe ones side by side and keeps the rest in order.

Why order matters

Systems communicate through data, so each one sees whatever the previous ones left behind:

  • Movement before rendering: the picture shows this frame's positions.
  • AI before movement: AI decides a heading, movement applies it. Reversed, everything reacts one frame late.
  • Input before AI: the enemies see where the player is now, not where they were.

Run in the wrong order and nothing crashes. The game just feels laggy or inconsistent, which is the worst kind of bug to find.

Declaring access

Each system states the data it reads and the data it writes. "Data" means component types, and also resources: singletons such as Time or Input that belong to the world rather than to one entity. Declarations let the engine reason about systems without running them.

Two systems conflict when one of them writes something the other reads or writes:

reads  A, reads  A   no conflict   (both only look)
reads  A, writes A   conflict      (reader may see a half-updated world)
writes A, writes A   conflict      (last writer wins, order decides the result)
writes A, writes B   no conflict   (disjoint data)

Conflicting systems must run one after the other. Non-conflicting systems can run at the same time on different threads. That is how Bevy and similar engines use all the cores without locks.

Two more tools:

  • Explicit ordering. A system may say it must run after another even when their data is disjoint, for example "show the score after the game rules ran".
  • Exclusive systems. One that needs the whole world (applying queued spawns and despawns, saving a game) is declared as writing everything; it conflicts with every other system and runs alone.

From conflicts to stages

Keep the order systems were registered in; it breaks every tie and makes frames reproducible. Then place each system, in that order, into the earliest stage that comes after every earlier system it conflicts with or must follow. Systems in the same stage can run in parallel; stages run one after another.

Worked example with different material:

SYSTEM spawner  -        Enemies   -
SYSTEM health   Armor    Hp        -
SYSTEM poison   Hp       Hp        -
SYSTEM minimap  Enemies  -         -
SYSTEM hud      Hp,Armor -         spawner
  • spawner conflicts with nothing: stage 0.
  • health writes Hp, nothing earlier touches Hp: stage 0.
  • poison reads and writes Hp, conflicts with health: stage 1.
  • minimap reads Enemies, conflicts with spawner: stage 1.
  • hud reads Hp, so it follows health and poison (stage 2); it also names spawner, which is only stage 0: stage 2.
stage 0: spawner health
stage 1: poison minimap
stage 2: hud

Common mistakes

  • Treating two readers as a conflict. Read-only access is the whole reason parallelism is possible.
  • Treating a reader registered before a writer as harmless. The writer still must not run beside it.
  • Taking only the previous system into account. A system must wait for the latest conflicting stage among all earlier ones.
  • Forgetting that an exclusive system conflicts even with systems that declare no access at all.
  • Moving a system to an earlier stage than a system it follows because their data is disjoint.

Your exercise

Build the scheduler described in the exercise. The starter parses the declarations and prints the stages; you write the function that assigns each system its stage. The most likely mistake is looking only at the previous system.

Up nextEvents & MessagingEntity-Component System

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…