- Fix `ref` keyword used as variable name in code examples - Fix "retries next tick" → systems continue on normal schedule - Fix `State::set()` → `NextState::set()` in upgrade skill - Fix `SceneRoot` → `WorldAssetRoot` for 0.19 consistency - Fix Replace lifecycle event description (overwritten, not removed) - Fix grep patterns (quoting, trailing spaces) - Remove third-party physics/networking content (not Bevy built-ins)
4.1 KiB
0.17 → 0.18
The largest recent transition. Its centerpiece — the Event/Message split — is architectural, not just a rename. Official guide for the long tail: https://bevy.org/learn/migration-guides/0-17-to-0-18/.
The Event/Message split
The old buffered event system was split in two:
| Old (≤0.17) | New (0.18) |
|---|---|
#[derive(Event)] (buffered use) |
#[derive(Message)] |
EventWriter<T> / .send(e) |
MessageWriter<T> / .write(m) |
EventReader<T> |
MessageReader<T> |
Events<T> |
Messages<T> |
on_event::<T>() run condition |
on_message::<T>() |
Event still exists but now means observer-events only (commands.trigger() + On<E> observers, immediate push). This is the transition's biggest trap: a type ported to #[derive(Event)] and written with a MessageWriter won't compile, but a type left as Event with a forgotten reader silently does nothing.
Port rule: every buffered event → Message. Only convert to Event+observer deliberately, during post-migration cleanup, where immediate reaction is actually wanted.
New in 0.18: #[derive(EntityEvent)] with #[event_target] for entity-targeted events, optionally #[entity_event(propagate)] to bubble up ChildOf.
Renames & moves (mechanical)
| Old | New |
|---|---|
remove_child / remove_children / clear_children |
detach_child / detach_children / detach_all_children |
bevy::render::render_resource::ShaderRef |
bevy::shader::ShaderRef |
WinitPlugin::<WakeUp> |
WinitPlugin (no longer generic) |
AmbientLight (single type) |
GlobalAmbientLight resource + AmbientLight camera component |
Camera.target field |
RenderTarget required component |
GltfPlugin use_model_forward_direction |
convert_coordinates + rotate_scene_entity / rotate_meshes flags |
API shape changes
- Fallible systems: systems may return
Result(=Result<(), BevyError>); errors are logged and the system continues running on its normal schedule. Adopt during the bump wherever it deletesunwrap()s cheaply; systematically during cleanup. - Mesh accessors became
try_*returningResult<_, MeshAccessError>. MaterialPluginfieldsprepass_enabled/shadows_enabledbecameMaterialtrait methods.LoadContext::path()returnsAssetPath, notPath; imagereinterpret_*methods returnResult.- Immutable components:
#[component(immutable)]available. - Input feature gates:
mouse,keyboard,gamepad,touch,gesturesare now cargo features. Default-on, but builds withdefault-features = falsemust list them — otherwise input silently stops arriving.
Semantic shifts (audit, don't just compile)
NextState::set()same-state transitions fire.set(Playing)while inPlayingnow triggersOnExit(Playing)+OnEnter(Playing)(previously a no-op). One-time setup inOnEnter(spawn camera, load level) re-runs. Audit everynext_state.set(...)reachable while already in that state; useset_if_neq()where the old behavior is wanted.- Material shader bind groups: material bindings are
@group(3);@group(2)is the mesh storage buffer. Old custom shaders using@group(2)fail withStorage class Storage doesn't match the shader Uniform. Update all.wgslmaterial shaders. MouseMotion,MouseWheeland other input streams are Messages now — readers must beMessageReader.
Porting checklist
grep -rn "EventWriter\|EventReader\|on_event\|Events<"— rename to Message equivalents;.send(→.write(.grep -rn "derive(Event)"— decide per type: buffered (→Message) or observed (staysEvent, needs a trigger + observer).grep -rn "remove_child\|clear_children"— rename todetach_*.grep -rn "next_state.set\|NextState"— audit same-state re-fire.grep -rn "@group(2)" --include="*.wgsl"— move material bindings to group 3.grep -rn "AmbientLight"— split into resource vs camera component usage.- Check
Cargo.tomlfordefault-features = falseon bevy → add input features.