c661027d19
Replace scaffold placeholders with full skill content: - bevy-0.19: ECS cheat sheet, critical traps table, architecture guide, and 7 reference files - bevy-upgrade: version migration workflow, transition references for 0.15→0.19, and 3 per-bump reference files
88 lines
4.3 KiB
Markdown
88 lines
4.3 KiB
Markdown
# 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<T>` | shared read |
|
|
| `ResMut<T>` | exclusive write |
|
|
| `Option<Res<T>>` / `Option<ResMut<T>>` | may not exist (mandatory for render resources in headless-capable systems) |
|
|
| `Local<T>` | per-system private state, default-initialized, persists across runs |
|
|
| `NonSend<T>` / `NonSendMut<T>` | `!Send` resources (main-thread only) |
|
|
|
|
World/App: `init_resource::<R>()`, `insert_resource(value)`, `remove_resource::<R>()`.
|
|
|
|
**0.19**: Resources implement `Component` and live on dedicated entities. Consequences:
|
|
- `Query<Entity>` (and other very broad queries) match resource entities — filter with `Without<IsResource>`.
|
|
- 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<T>`, `DeferredWorld`, `&World`, `Option<P>`, `Result<P, SystemParamValidationError>`.
|
|
|
|
- `Single<D, F>` — resolves to exactly one entity or the system doesn't run correctly (panics); the param-level version of `query.single()`.
|
|
- `Populated<D, F>` — the system is skipped when the query is empty. Cheap way to avoid per-frame no-op runs.
|
|
|
|
## Queries
|
|
|
|
`Query<D, F>` — `D: QueryData`, `F: QueryFilter` (default `()`).
|
|
|
|
Data: `&T`, `&mut T`, `Entity`, `Has<T>`, tuples.
|
|
|
|
Filters:
|
|
|
|
| Filter | Matches |
|
|
|--------|---------|
|
|
| `With<T>` / `Without<T>` | presence / absence |
|
|
| `Added<T>` | first tick after the component was added |
|
|
| `Changed<T>` | first tick after add or mutable deref |
|
|
| `Spawned` | first tick after entity spawn |
|
|
| `Or<(A, B)>` | either |
|
|
|
|
Note `Changed<T>` 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::<T>()` | 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.
|