Install
$ agentstack add skill-chrisgliddon-bevy-skills-bevy-ecs-systems ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Bevy 0.18 — ECS Systems (params, sets, run conditions)
When to use this skill
- Bundling related state into a single system parameter via
#[derive(SystemParam)]. - Grouping systems into a
SystemSetso callers can order against the whole group. - Gating systems with run conditions (
run_if,on_message,in_state,resource_exists,any_with_component). - Hooking into state transitions with
OnEnter(S)/OnExit(S)/OnTransition { from, to }. - Hot-removing systems at runtime (e.g. tearing down a debug overlay) with
remove_systems_in_set. - Hitting
ScheduleBuildErrorambiguity panics — the executor no longer guesses.
Canonical pattern
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
#[derive(SystemSet, Hash, PartialEq, Eq, Clone, Debug)]
enum GameLoop { Input, Simulate, Render }
#[derive(States, Default, Hash, PartialEq, Eq, Clone, Debug)]
enum AppState { #[default] Loading, Playing }
#[derive(Resource, Default)]
struct Score(u32);
#[derive(Message)]
struct GoalScored { team: u8 }
// Composite param: pass one argument, get four.
// 'w = world borrow; 's = system-local state borrow.
#[derive(SystemParam)]
struct GameCtx {
time: Res,
score: ResMut,
goals: MessageReader,
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_resource::()
.add_message::()
.init_state::()
.configure_sets(Update, (GameLoop::Input, GameLoop::Simulate, GameLoop::Render).chain())
// State schedule: fires once when entering Playing.
.add_systems(OnEnter(AppState::Playing), spawn_level)
// State schedule: fires once when leaving Playing.
.add_systems(OnExit(AppState::Playing), despawn_level)
.add_systems(Update, read_input.in_set(GameLoop::Input))
.add_systems(
Update,
tally_goals
.in_set(GameLoop::Simulate)
.run_if(on_message::),
)
.add_systems(Update, draw_hud.in_set(GameLoop::Render))
.run();
}
#[derive(Component)]
struct LevelEntity;
fn spawn_level(mut commands: Commands) {
commands.spawn((LevelEntity, Name::new("level")));
}
fn despawn_level(mut commands: Commands, query: Query>) {
for e in &query { commands.entity(e).despawn(); }
}
fn read_input(mut writer: MessageWriter) {
writer.write(GoalScored { team: 0 });
}
fn tally_goals(mut ctx: GameCtx) {
let _ = ctx.time.delta_secs();
for goal in ctx.goals.read() {
ctx.score.0 += 1;
info!("team {} scored, total {}", goal.team, ctx.score.0);
}
}
fn draw_hud(score: Res) { let _ = score.0; }
Run condition cheat sheet
| Built-in | Triggers when | |---|---| | on_message:: | The Messages buffer has unread items. | | resource_exists:: | Resource R is in the World. | | resource_changed:: | R was mutated this tick. | | in_state(MyState::X) | Current State equals X. | | state_changed:: | The state changed this tick. | | any_with_component:: | At least one entity has C. |
Combine with .and() / .or(): run_if(in_state(GameState::Playing).and(resource_exists::())).
Topics
| Topic | Reference | |---|---| | #[derive(SystemParam)], 'w/'s lifetimes, Local, Commands deferred apply | [references/system-params.md](references/system-params.md) | | #[derive(SystemSet)] requirements, .in_set, .configure_sets, .chain() | [references/system-sets.md](references/system-sets.md) | | Every built-in condition, .and()/.or()/not(), custom conditions, cost rule | [references/run-conditions.md](references/run-conditions.md) | | OnEnter(S) / OnExit(S) / OnTransition, NextState, set_if_neq | [references/state-schedules.md](references/state-schedules.md) | | .before, .after, .chain(), .ambiguous_with, debugging ambiguity errors | [references/ordering.md](references/ordering.md) | | remove_systems_in_set, ScheduleCleanupPolicy, 3-arg vs 4-arg receivers, side-effect limits | [references/runtime-removal.md](references/runtime-removal.md) |
Gotchas (0.18)
SimpleExecutoris gone. Any ambiguity between systems sharing data is now a build-time error. Fix with.before,.after,.chain(), or.ambiguous_with(other)(explicit accept). See [references/ordering.md](references/ordering.md).MessageReader/MessageWriter, notEventReader/EventWriter. Renamed in 0.17. Trait derive is#[derive(Message)]; registrar isapp.add_message::().next_state.set(S)always firesOnExit/OnEnterin 0.18. Useset_if_neqfor the old behaviour. See [references/state-schedules.md](references/state-schedules.md).Schedules::remove_systems_in_settakes 4 args in 0.18 (schedule_label,set,world,ScheduleCleanupPolicy);Schedule::remove_systems_in_settakes 3. See [references/runtime-removal.md](references/runtime-removal.md).
See also
bevy-core-concepts— which schedule (Startup,Update,FixedUpdate) to add a system to.bevy-ecs-queries— query is one of manySystemParams;Changed/Addedfilters.bevy-ecs-components— defining theComponenttypes your systems act on.bevy-migration-0-17-to-0-18— full Message/Event rename,MaterialPluginchanges.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: chrisgliddon
- Source: chrisgliddon/bevy-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.