# 0.15 → 0.16 → 0.17 The 0.16 transition restructured hierarchy and spawning; 0.17 was comparatively quiet. Both are covered here. For changes not listed, consult the official guides: `https://bevy.org/learn/migration-guides/0-15-to-0-16/` and `.../0-16-to-0-17/`. ## Renames & removals (mechanical) | Old (≤0.15) | New (0.16+) | Notes | |-------------|-------------|-------| | `Parent` component | `ChildOf(pub Entity)` | Lives on the child; entities *with* `ChildOf` are children | | `*parent` (Deref to Entity) | `child_of.parent()` | Deref removed | | `despawn_recursive()` | `despawn()` | `despawn()` is now recursive by default | | `despawn_descendants()` | `despawn_related::()` | | | `#[derive(Bundle)]` | spawn tuples + `#[require(...)]` | Bundles removed as a user-facing pattern | | `StateScoped(state)` | `DespawnOnExit(state)` / `DespawnOnEnter(state)` | | | `parent_entity()` (child spawner) | `target_entity()` | | ## API shape changes - **Hierarchy is relationship-based**: `ChildOf` implements `Relationship`, `Children` implements `RelationshipTarget`; they sync automatically via hooks. Delete any manual `Children` bookkeeping — it now fights the engine. - **Spawning children**: `commands.spawn((Comp, ChildOf(parent)))` works directly; `with_children(|spawner| ...)` remains. `add_child` / `add_children` / `insert_children` attach existing entities. - **`Children` iteration** yields `Entity` via `IntoIterator`: `for child in &children`. Ports of `children.iter().copied()` compile but are noise — simplify during cleanup. - **Required components** replace bundles: `#[require(Transform, Visibility)]` on a marker pulls in dependencies at spawn. When porting a `Bundle` struct, its fields usually become either a spawn tuple at call sites or `#[require(...)]` on the primary component. - Query relationship extensions appear: `query.related::(entity)`, `query.relationship_sources::(entity)`. ## Semantic shifts (audit, don't just compile) - **`despawn()` is recursive.** Code that relied on `despawn()` orphaning children (intentionally detaching them) now destroys them. If detach-then-despawn was the intent, `detach_all_children()` first (name as of 0.18; `clear_children()` in 0.16–0.17). - **Adding `ChildOf` has side effects**: parent's `Children` updates immediately via hooks, and lifecycle observers on `Children` fire. Ordering assumptions around manual parent updates are void. ## Porting checklist 1. `grep -rn "Parent\b"` — replace with `ChildOf`, fix accessors to `.parent()`. 2. `grep -rn "despawn_recursive\|despawn_descendants"` — rename; then audit remaining plain `despawn()` calls for the orphaning assumption. 3. `grep -rn "derive(Bundle)"` — convert to tuples/`#[require]`. 4. `grep -rn "StateScoped"` — replace with `DespawnOnExit`/`DespawnOnEnter`. 5. Remove manual child-list maintenance (observers/systems pushing into `Children`).