Files
g4borg 325e278af1 Scaffold bevy plugin with bevy-0.19 and bevy-upgrade skills
Add plugin skeleton with versioned skill directories, TODO SKILL.md
scaffolds with goals for skill-creator, and copy over bevy-skill-research
reports from spacecraft into docs/workpad/research/.
2026-07-07 17:52:00 +02:00

2.9 KiB

Bevy Skill Research: Hierarchy & Relationships

Bevy version: 0.18, with 0.19 notes
Date: 2026-07-07

ChildOf Replaces Parent (Bevy 0.16+)

  • Parent renamed to ChildOf(pub Entity) — "entities with ChildOf are children, not parents"
  • Deref removed; use child_of.parent() to get the parent Entity
  • ChildOf implements Relationship; Children implements RelationshipTarget — they auto-sync via hooks
  • Adding ChildOf(parent) to child auto-inserts Children on parent; removing it auto-updates parent
  • Despawning a parent auto-despawns all descendants (was despawn_recursive, now just despawn())

Spawning Children

// Insert ChildOf directly
commands.spawn(ChildOf(parent));

// Inline child on parent
commands.entity(parent).with_child((SpriteBundle::default(), ChildOf(parent)));

// Multiple children via closure
commands.spawn_empty().with_children(|spawner: &mut ChildSpawnerCommands| {
    spawner.spawn(MyComponent(255));
    let parent = spawner.target_entity(); // was parent_entity()
});

// Add existing entities as children
commands.entity(parent).add_child(child);
commands.entity(parent).add_children(&[child1, child2]);
commands.entity(parent).insert_children(index, &[child1, child2]);

Querying Hierarchy

  • Children derefs to [Entity], implements IntoIterator
  • Correct iteration: for child in &children or children.into_iter()
  • Wrong: children.iter().copied() — unnecessary, IntoIterator yields Entity directly
  • Methods: len(), is_empty(), contains(), first(), last(), sort_by()
  • Query extensions (0.16+): query.related::<ChildOf>(entity), query.relationship_sources::<Children>(entity)

Detaching vs Despawning (0.18 Renames)

Old name (≤0.17) New name (0.18+) Effect
remove_children detach_children Detach only, do NOT despawn
clear_children detach_all_children Detach all, do NOT despawn
remove_child detach_child Detach one, do NOT despawn

To actually despawn children: despawn_related::<Children>()

Transform Propagation

  • GlobalTransform is auto-propagated through ChildOf hierarchy
  • Child Transform is relative to parent; GlobalTransform is computed world-space
  • Propagation runs in PostUpdate — reading GlobalTransform in Update gives stale (last-frame) values

Common Mistakes

Mistake Correct
Parent component ChildOf(entity)
children.iter().copied() children.into_iter() or for child in &children
*child_of (deref) child_of.parent()
despawn_recursive() despawn() (auto-recursive now)
parent_entity() in spawner target_entity()
clear_children() detach_all_children() (0.18+)
remove_children() detach_children() (0.18+)
Reading GlobalTransform in Update Read in PostUpdate, or accept one-frame lag