# ECS Core Reference ## Components `#[derive(Component)]` on structs/enums; requires `Send + Sync + 'static`. Storage: - Table (default) — fast iteration. - `#[component(storage = "SparseSet")]` — fast insert/remove; use for tag-like components that churn. Attributes: - `#[component(immutable)]` (0.18+) — only `&T` access, never `&mut T`. Good for identity-like data. - `#[require(B, C)]` — auto-insert `B` and `C` when this component is added. Constructor forms: `B(value)`, `C { field: val }`, function calls, `= expr`. This replaced `#[derive(Bundle)]` (removed 0.16+); spawn with tuples instead. - Hooks: `#[component(on_add = f)]`, `on_insert`, `on_replace`, `on_remove`, `on_despawn`. Hook signature: `fn(DeferredWorld, HookContext)`. Hooks run synchronously inside the ECS operation. - `#[component(clone_behavior = Ignore)]` — skip during entity clone. ## Resources | Param | Access | |-------|--------| | `Res` | shared read | | `ResMut` | exclusive write | | `Option>` / `Option>` | may not exist (mandatory for render resources in headless-capable systems) | | `Local` | per-system private state, default-initialized, persists across runs | | `NonSend` / `NonSendMut` | `!Send` resources (main-thread only) | World/App: `init_resource::()`, `insert_resource(value)`, `remove_resource::()`. **0.19**: Resources implement `Component` and live on dedicated entities. Consequences: - `Query` (and other very broad queries) match resource entities — filter with `Without`. - A type cannot derive both `Component` and `Resource`. ## Systems Any `fn(params...)` where every param is a `SystemParam`. - **Fallible** (0.18+): `fn system(...) -> Result` (alias for `Result<(), BevyError>`). Errors are logged; the system runs again next tick. `?` converts anything convertible to `BevyError`. Prefer this over `unwrap()`. - **Exclusive**: `fn system(world: &mut World)` — full access, blocks parallelism; use sparingly. Valid `SystemParam` types include: `Query`, `Res`, `ResMut`, `Commands`, `Local`, `MessageReader`, `MessageWriter`, `ParamSet`, `Single`, `Populated`, `SystemName`, `SystemChangeTick`, `RemovedComponents`, `DeferredWorld`, `&World`, `Option

`, `Result`. - `Single` — resolves to exactly one entity or the system doesn't run correctly (panics); the param-level version of `query.single()`. - `Populated` — the system is skipped when the query is empty. Cheap way to avoid per-frame no-op runs. ## Queries `Query` — `D: QueryData`, `F: QueryFilter` (default `()`). Data: `&T`, `&mut T`, `Entity`, `Has`, tuples. Filters: | Filter | Matches | |--------|---------| | `With` / `Without` | presence / absence | | `Added` | first tick after the component was added | | `Changed` | first tick after add or mutable deref | | `Spawned` | first tick after entity spawn | | `Or<(A, B)>` | either | Note `Changed` triggers on `&mut` deref even without an actual value change — deref only when writing. Methods: `.iter()` / `.iter_mut()`, `.get(entity)` / `.get_mut(entity)`, `.single()` (Result-returning; panicking use is a bug magnet), `.par_iter()` / `.par_iter_mut()`. Reusable shapes: `#[derive(QueryData)]`, `#[derive(QueryFilter)]`. ## Commands | Call | Effect | |------|--------| | `commands.spawn((A, B))` | spawn with component tuple, returns `EntityCommands` | | `commands.spawn_empty()` | empty entity, chain `.insert(...)` | | `commands.spawn_batch(iter)` | batch spawn | | `commands.entity(e).insert(c)` | add/replace component | | `commands.entity(e).insert_if_new(c)` | add only if absent | | `commands.entity(e).remove::()` | remove component | | `commands.entity(e).despawn()` | despawn entity **and descendants** | | `commands.queue(cmd)` | custom `Command` impl | Commands are deferred to the next sync point — a spawn is not queryable in the same system. ## Ordering - `(a, b).chain()` — sequential. - `.before(x)` / `.after(x)` — explicit constraints against systems or sets. - `#[derive(SystemSet)]` + `app.configure_sets(Update, SetA.before(SetB))` — named groups; the scalable way to order across plugins. - Systems with overlapping mutable access and no ordering run nondeterministically; Bevy warns about ambiguities. Order anything where results depend on it.