Archetype ECS architecture

Composition becomes a data layout.

Archetype tables group equal entity shapes so queries can process compatible component columns as contiguous batches.

One component set identifies one table

The component set is an entity's runtime shape. Entities with the same set share a table, even when their names and gameplay roles differ.

EntityComponent setTable
PlayerPosition, Velocity, HealthMoving actor
EnemyPosition, Velocity, HealthMoving actor
TreePosition, HealthStatic actor

The player and enemy share rows because their data shape is identical. The tree belongs to another table because its shape has no velocity.

Data components occupy separate columns

A table stores entity handles and one array for each data component:

entities: [player, enemy, ...]
Position: [p0,     p1,    ...]
Velocity: [v0,     v1,    ...]
Health:   [h0,     h1,    ...]

A movement system can walk position and velocity arrays in lockstep. The component access is resolved for the batch, then the inner loop works on the rows directly.

Queries match tables before iterating rows

Terms define required data and access mode. A persistent query records the table ids that satisfy those terms and adds compatible tables as the world grows.

ecs_query_id_t moving = ecs_query({
    .terms = {
        ecs_inout(Position),
        ecs_in(Velocity),
        ecs_filter(Visible),
    },
});

Fields expose data to the callback. Filter terms participate in matching without adding a data field, which keeps the query contract precise.

Changing composition selects a new table

Updating an existing value writes to its current column. Adding or removing a component changes the entity shape and moves it to the table for that shape.

  1. Find or create the destination table.
  2. Allocate the destination row.
  3. Move values shared by both shapes.
  4. Initialize added data and release removed data.
  5. Update the entity record and table row.

Tags add state without a data column

A tag is a zero-sized component. It changes the entity shape and query matching without allocating a data array. Tags work well for stable state such as Player, Visible, and Selected.

Systems reuse the matching table set

A system owns a persistent query, a callback, and a phase. Each run visits the matching tables and passes the component columns to the callback as batches.

The result is a direct path from composition to execution: entity shapes select tables, query terms select tables, and systems process their rows.