hierarchy/hierarchy.rs
1//! Demonstrates techniques for creating a hierarchy of parent and child entities.
2//!
3//! When [`DefaultPlugins`] are added to your app, systems are automatically added to propagate
4//! [`Transform`] and [`Visibility`] from parents to children down the hierarchy,
5//! resulting in a final [`GlobalTransform`] and [`InheritedVisibility`] component for each entity.
6
7use std::f32::consts::*;
8
9use bevy::{color::palettes::css::*, prelude::*};
10
11fn main() {
12 App::new()
13 .add_plugins(DefaultPlugins)
14 .add_systems(Startup, setup)
15 .add_systems(Update, rotate)
16 .run();
17}
18
19fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
20 commands.spawn(Camera2d);
21 let texture = asset_server.load("branding/icon.png");
22
23 // Spawn a root entity with no parent
24 let parent = commands
25 .spawn((
26 Sprite::from_image(texture.clone()),
27 Transform::from_scale(Vec3::splat(0.75)),
28 ))
29 // With that entity as a parent, run a lambda that spawns its children
30 .with_children(|parent| {
31 // parent is a ChildSpawnerCommands, which has a similar API to Commands
32 parent.spawn((
33 Transform::from_xyz(250.0, 0.0, 0.0).with_scale(Vec3::splat(0.75)),
34 Sprite {
35 image: texture.clone(),
36 color: BLUE.into(),
37 ..default()
38 },
39 ));
40 })
41 // Store parent entity for next sections
42 .id();
43
44 // Another way is to use the add_child function to add children after the parent
45 // entity has already been spawned.
46 let child = commands
47 .spawn((
48 Sprite {
49 image: texture,
50 color: LIME.into(),
51 ..default()
52 },
53 Transform::from_xyz(0.0, 250.0, 0.0).with_scale(Vec3::splat(0.75)),
54 ))
55 .id();
56
57 // Add child to the parent.
58 commands.entity(parent).add_child(child);
59}
60
61// A simple system to rotate the root entity, and rotate all its children separately
62fn rotate(
63 mut commands: Commands,
64 time: Res<Time>,
65 mut parents_query: Query<(Entity, &Children), With<Sprite>>,
66 mut transform_query: Query<&mut Transform, With<Sprite>>,
67) {
68 for (parent, children) in &mut parents_query {
69 if let Ok(mut transform) = transform_query.get_mut(parent) {
70 transform.rotate_z(-PI / 2. * time.delta_secs());
71 }
72
73 // To iterate through the entities children, just treat the Children component as a Vec
74 // Alternatively, you could query entities that have a ChildOf component
75 for child in children {
76 if let Ok(mut transform) = transform_query.get_mut(*child) {
77 transform.rotate_z(PI * time.delta_secs());
78 }
79 }
80
81 // To demonstrate removing children, we'll remove a child after a couple of seconds.
82 if time.elapsed_secs() >= 2.0 && children.len() == 2 {
83 let child = children.last().unwrap();
84 commands.entity(*child).despawn();
85 }
86
87 if time.elapsed_secs() >= 4.0 {
88 // This will remove the entity from its parent's list of children, as well as despawn
89 // any children the entity has.
90 commands.entity(parent).despawn();
91 }
92 }
93}