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
3.7 KiB
Plugins, App, States, Schedules
Plugin trait (bevy::app::Plugin)
Required:
fn build(&self, app: &mut App)— runs immediately onadd_plugins.
Optional (defaults provided):
fn ready(&self, _: &App) -> bool— defaulttrue; override for async init.fn finish(&self, _: &mut App)— runs after all plugins reportready(), before the first schedule tick. The idiomatic place for cross-plugin setup that needs another plugin's resources to exist.fn cleanup(&self, _: &mut App)— runs afterfinish(); remove temp resources.fn name(&self) -> &str— defaults to type name; used for the uniqueness check.fn is_unique(&self) -> bool— defaulttrue; returnfalsefor multi-instance plugins.
Any fn(&mut App) auto-implements Plugin.
Plugin dependencies
There is no formal depends-on declaration. Patterns:
app.is_plugin_added::<T>()to guard or panic early with a clear message.- Sub-plugins: call
app.add_plugins(ChildPlugin)insidebuild(). Bevy deduplicates by name; unique plugins panic on double-add. - Cross-plugin wiring that needs the other plugin's resources →
finish().
Plugin groups
DefaultPlugins / MinimalPlugins implement PluginGroup. Customize via the builder:
DefaultPlugins
.disable::<AudioPlugin>()
.set(WindowPlugin { /* config */ })
.add_before::<RenderPlugin>(MyPlugin)
.disable::<T>(), .enable::<T>(), .set(plugin), .add_before::<Target>(p), .add_after::<Target>(p).
App builder key methods
| Method | Purpose |
|---|---|
add_plugins(P) |
Plugin, plugin group, or tuple of either |
insert_resource(R) |
Insert, overwriting existing |
init_resource::<R>() |
Insert via Default/FromWorld if absent |
add_systems(schedule, systems) |
Add to a schedule |
configure_sets(schedule, sets) |
Order system sets |
register_type::<T>() |
Reflection registry |
is_plugin_added::<T>() |
Plugin presence check |
register_required_components::<T, R>() |
Runtime component requirements |
States
Three flavors:
- FreelyMutableState — changed via the
NextState<S>resource. - SubStates — exist only while the parent state is in a required variant.
- ComputedStates — derived:
fn compute(sources) -> Option<Self>.
Registration: app.init_state::<S>() (default initial) or app.insert_state(value).
Transition schedules: OnEnter(S), OnExit(S), OnTransition(S).
Entity scoping: DespawnOnEnter(S), DespawnOnExit(S) (replaced StateScoped, 0.16+).
Run condition: in_state(S).
0.18 behavior change: NextState::set() fires OnExit+OnEnter even when setting the current state. Use set_if_neq() for no-op-on-same. One-time setup in OnEnter systems will re-run if any caller set()s the active state.
Schedules
| Phase | Schedules |
|---|---|
| Startup (once) | PreStartup, Startup, PostStartup |
| Per-frame | First, PreUpdate, Update, PostUpdate, Last |
| Fixed timestep | FixedFirst, FixedPreUpdate, FixedUpdate, FixedPostUpdate, FixedLast (inside FixedMain, driven by RunFixedMainLoop) |
| Other | Main, SpawnScene |
Gameplay simulation that must be framerate-independent goes in FixedUpdate. Transform propagation and most engine bookkeeping run in PostUpdate.
Run conditions (common_conditions)
in_state(s)resource_exists::<R>(),resource_added::<R>(),resource_changed::<R>(),resource_equals(val)any_with_component::<T>(),any_component_removed::<T>()on_message::<M>()(renamed fromon_event, 0.18)run_once(),not(cond),condition_changed(cond),condition_changed_to(cond)
Combine with .and(cond) / .or(cond).