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
4.3 KiB
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&Taccess, never&mut T. Good for identity-like data.#[require(B, C)]— auto-insertBandCwhen 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 withWithout<IsResource>.- A type cannot derive both
ComponentandResource.
Systems
Any fn(params...) where every param is a SystemParam.
- Fallible (0.18+):
fn system(...) -> Result(alias forResult<(), BevyError>). Errors are logged; the system runs again next tick.?converts anything convertible toBevyError. Prefer this overunwrap(). - 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 ofquery.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.