Bevy System Parameters Cheatsheet

Complete reference of all system parameter types available in Bevy 0.15+.

System Parameters

TypePurposeExampleNotes
Query<&T>Read component data from entitiesQuery<&Transform>Iterates all entities with Transform
Query<&mut T>Write component dataQuery<&mut Health>Requires mut query binding
Query<(&A, &B)>Read multiple componentsQuery<(&Transform, &Velocity)>Only matches entities with both
Query<(&mut A, &B)>Mix read and writeQuery<(&mut Transform, &Velocity)>Some mutable, some read-only
Query<Entity>Get entity IDs onlyQuery<Entity, With<Player>>Lightweight, no component data fetched
Query<&T, With<U>>Read with filterQuery<&Health, With<Player>>Fetch Health only from Player entities
Query<&T, Without<U>>Exclude filterQuery<&Health, Without<Invincible>>Skip entities that have Invincible
Query<&T, Changed<T>>Changed filterQuery<&Health, Changed<Health>>Only entities whose Health changed this tick
Query<&T, Added<T>>Added filterQuery<&Health, Added<Health>>Only entities that just received Health
Query<&T, (With<A>, Without<B>)>Combined filtersQuery<&Health, (With<Enemy>, Without<Shield>)>Tuple of filters = AND logic
Query<(&A, Option<&B>)>Optional componentQuery<(&Transform, Option<&Velocity>)>Matches all with Transform; Velocity may be None
Single<&T>Exactly one entity (0.15+)Single<&Transform, With<Player>>Panics if zero or multiple matches. Use for unique entities
Res<T>Read-only resourceRes<Time>Panics if resource does not exist
ResMut<T>Mutable resourceResMut<Score>Requires mut score binding
Option<Res<T>>Optional resource (read)Option<Res<Score>>Returns None if resource not inserted
Option<ResMut<T>>Optional resource (write)Option<ResMut<Score>>Returns None if resource not inserted
CommandsDeferred world mutationsCommandsSpawn, despawn, insert/remove components. Applied between system sets
EventReader<T>Read eventsEventReader<DamageEvent>Tracks read position automatically. Events persist for 2 frames
EventWriter<T>Send eventsEventWriter<DamageEvent>Use .send(event) to emit
Local<T>Per-system local stateLocal<u32>Persists across system runs. Each system instance gets its own copy. T: Default required
ParamSet<(Q1, Q2)>Conflicting queriesParamSet<(Query<&mut A, With<B>>, Query<&mut A, Without<B>>)>Use when two queries would conflict. Access via .p0(), .p1()
NonSend<T>Non-Send resource (read)NonSend<WinitWindows>For resources that must stay on the main thread
NonSendMut<T>Non-Send resource (write)NonSendMut<WinitWindows>Forces system to run on main thread
Deferred<T>Custom deferred mutationsDeferred<MyBuffer>Batches writes that apply later. T: SystemBuffer required

Query Filter Types

FilterMatchesExample
With<T>Entities that have component TQuery<&Health, With<Player>>
Without<T>Entities that do NOT have component TQuery<&Health, Without<Invincible>>
Changed<T>Entities whose T was mutated this tickQuery<&Transform, Changed<Transform>>
Added<T>Entities that received T this tickQuery<Entity, Added<Enemy>>
Or<(F1, F2)>Entities matching any filterQuery<&Name, Or<(With<Player>, With<Ally>)>>

Common Query Patterns

#![allow(unused)]
fn main() {
// Iterate all matches
for (transform, velocity) in &query { }

// Iterate with mutation
for (mut transform, velocity) in &mut query { }

// Get specific entity
if let Ok(health) = query.get(entity) { }
if let Ok(mut health) = query.get_mut(entity) { }

// Check if entity matches
let exists = query.contains(entity);

// Single result (panics if not exactly one)
let player_transform = single_query.into_inner();

// Count matches
let enemy_count = query.iter().count();

// Check if any matches exist
let has_enemies = !query.is_empty();
}

ParamSet Usage

When two queries in the same system would conflict (both accessing the same component mutably, or one reading and one writing), use ParamSet:

#![allow(unused)]
fn main() {
fn system(mut params: ParamSet<(
    Query<&mut Transform, With<Player>>,
    Query<&mut Transform, With<Enemy>>,
)>) {
    // Access one at a time — cannot hold both simultaneously
    for mut transform in params.p0().iter_mut() {
        transform.translation.x += 1.0;
    }
    for mut transform in params.p1().iter_mut() {
        transform.translation.x -= 1.0;
    }
}
}

Trigger (Observer Systems)

Observer systems use Trigger<T> instead of regular system parameters:

#![allow(unused)]
fn main() {
fn on_damage(
    trigger: Trigger<DamageEvent>,
    mut query: Query<&mut Health>,
) {
    let event = trigger.event();
    let target = trigger.target();
    if let Ok(mut health) = query.get_mut(target) {
        health.0 -= event.amount;
    }
}
}