Query — Reference¶
Purpose¶
A Query iterates all entities that have all required component types, efficiently by scanning only the matching archetypes (tables).
API¶
world.query(...ctors: ComponentCtor<any>[]): Iterable<any>¶
ctors is a list of component constructors (types) you want to require.
Queries yield rows shaped like:
e: theEntityc1,c2,c3, …: component values in the same order as thectorsarguments
So query(A, B, C) yields { e, c1: A, c2: B, c3: C }.
Row mapping and ordering¶
Deterministic component fields¶
The mapping is positional:
query(A)→{ e, c1 }query(A, B)→{ e, c1, c2 }query(A, B, C)→{ e, c1, c2, c3 }
And cN always corresponds to the Nth constructor you passed.
Example¶
1 2 3 4 5 6 7 |
This pattern is recommended explicitly for queries.
world.queryTables(...ctors: ComponentCtor<any>[]): Iterable<any>¶
ctors is a list of component constructors (types) you want to require.
Queries yield one item per matching archetype (table) (SoA columns + entity array):
entities:Entity[](row-aligned with all columns)c1,c2,c3, …: component columns (T[]) in the same order asctors
So queryTables(A, B, C) yields { entities, c1: A[], c2: B[], c3: C[] }.
Why queryTables?¶
Use this when you want fewer allocations and more cache-friendly loops:
- you iterate columns + indices instead of creating one
{e, c1, ...}object per entity - you can batch work per archetype
Example:
1 2 3 4 5 6 |
world.queryEach(...ctorsAndFn): void¶
Callback-based query: no generator, no yielded row objects.
1 2 3 4 5 6 7 |
queryEach(A, B, ...) calls fn(e, c1, c2, ...) where cN matches the Nth constructor argument.
So queryEach(A, B, C, fn) calls fn(e, A, B, C) in that order.
Why queryEach?¶
Use this when you want the simplest “do work per entity” loop without generator overhead:
1 2 3 4 5 6 7 |
Safety rules during iteration¶
While iterating a query (or while systems are running), structural changes (spawn/despawn/add/remove) can throw.
Use:
world.cmd()to defer changesworld.flush()(orworld.update()) to apply them safely