Skip to content

Entity Component System

Entity Component System (ECS) is an architecture that separates identity (entity), data (components), and behavior (systems). It is the data-oriented answer to the object-oriented entity hierarchies that buckle under thousands of objects. KBVE leans on it hard — Unity DOTS for rareicon, Bevy for the isometric/server crates.


  • Entity — an identity, usually just an integer ID. It owns no data and no behavior; it is a key that groups components.
  • Component — plain data, no logic. Position, Velocity, Health. An entity is the set of components attached to it.
  • System — behavior, no persistent data. A system queries for all entities that have a given set of components and processes them in a batch each frame.

The real payoff is memory layout. OOP scatters each object across the heap; chasing pointers thrashes the CPU cache. ECS stores components of the same type contiguously (struct-of-arrays). A system iterating Position + Velocity walks two tight arrays in order — the cache stays hot, the prefetcher wins.

  • Cache locality — process like data together; this is the Data Locality pattern made structural.
  • Parallelism — systems with non-overlapping component access run on different threads with no locks.
  • Composition over inheritance — add a capability by adding a component, not by editing a class tree.

  • Archetype-based (Unity DOTS, Bevy default) — entities with the same set of component types are grouped into “archetypes” / tables; iteration is a linear scan of matching tables. Fast iteration; adding/removing a component moves the entity between tables (structural change).
  • Sparse-set (Bevy opt-in, EnTT) — each component type owns a packed array plus an index map; cheap add/remove, slightly slower iteration.

Choose archetype for read-heavy hot loops, sparse-set for components that churn (frequently added/removed).


  • Query — “give me every entity with A and B, without C.” The system’s window into the world.
  • Change detection / change gate — skip entities whose data did not change since last run; avoid redundant work.
  • Structural changes — adding/removing components or creating/destroying entities. These often can’t happen mid-iteration; defer them via command buffers / entity command queues to a sync point.

Wins

Massive entity counts, cache-friendly, trivially parallel, data-driven composition, clean system boundaries.

Costs

Steeper mental model, harder debugging (no single “object”), structural-change rules, more ceremony for simple games.

ECS is overkill for a small game with few entities. It earns its complexity when you have thousands-to-millions of similar things to simulate every frame.


  • rareicon (Unity DOTS) — the deepest ECS adoption: Burst ISystem jobs, packed components, parallel event pipelines with NativeList.ParallelWriter, PipelineHandle/DrainHandle coordination, a multi-role job system where every unit carries every JobPriorities byte, and a micro-optimization checklist baked into every new system.
  • NetCode world split — under Unity NetCode the world is split; gameplay is client-only, so services scan World.All for KingTag rather than the default injection world.
  • Bevy crates — the isometric game and server-side crates (bevy_npc, bevy_skills, bevy_statemachine) use Bevy’s ECS for simulation and behavior.