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
87 lines
3.7 KiB
Markdown
87 lines
3.7 KiB
Markdown
# Plugins, App, States, Schedules
|
|
|
|
## Plugin trait (`bevy::app::Plugin`)
|
|
|
|
Required:
|
|
- `fn build(&self, app: &mut App)` — runs immediately on `add_plugins`.
|
|
|
|
Optional (defaults provided):
|
|
- `fn ready(&self, _: &App) -> bool` — default `true`; override for async init.
|
|
- `fn finish(&self, _: &mut App)` — runs after all plugins report `ready()`, 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 after `finish()`; remove temp resources.
|
|
- `fn name(&self) -> &str` — defaults to type name; used for the uniqueness check.
|
|
- `fn is_unique(&self) -> bool` — default `true`; return `false` for 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)` inside `build()`. 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:
|
|
|
|
```rust
|
|
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 from `on_event`, 0.18)
|
|
- `run_once()`, `not(cond)`, `condition_changed(cond)`, `condition_changed_to(cond)`
|
|
|
|
Combine with `.and(cond)` / `.or(cond)`.
|