concurrent_systems/
concurrent_systems.rs1use bevy_ecs::prelude::*;
25use bevy_entity_ptr::{EntityHandle, EntityPtr, WorldExt};
26
27#[derive(Component)]
30struct Name(&'static str);
31
32#[derive(Component)]
33struct Health(i32);
34
35#[derive(Component)]
36struct Armor(i32);
37
38#[derive(Component)]
39struct Children(Vec<EntityHandle>);
40
41#[derive(Component)]
42struct RootMarker;
43
44fn sum_health(node: EntityPtr) -> i32 {
46 let my_health = node.get::<Health>().map(|h| h.0).unwrap_or(0);
47
48 let children_health: i32 = node
49 .get::<Children>()
50 .map(|c| c.0.iter().map(|h| sum_health(node.follow_handle(*h))).sum())
51 .unwrap_or(0);
52
53 my_health + children_health
54}
55
56fn sum_armor(node: EntityPtr) -> i32 {
58 let my_armor = node.get::<Armor>().map(|a| a.0).unwrap_or(0);
59
60 let children_armor: i32 = node
61 .get::<Children>()
62 .map(|c| c.0.iter().map(|h| sum_armor(node.follow_handle(*h))).sum())
63 .unwrap_or(0);
64
65 my_armor + children_armor
66}
67
68fn compute_health_system(world: &World, query: Query<(Entity, &Name), With<RootMarker>>) {
75 for (entity, name) in &query {
76 let root_ptr = world.entity_ptr(entity);
77 let total_health = sum_health(root_ptr);
78 println!("[Health System] {} total health: {}", name.0, total_health);
79 }
80}
81
82fn compute_armor_system(world: &World, query: Query<(Entity, &Name), With<RootMarker>>) {
88 for (entity, name) in &query {
89 let root_ptr = world.entity_ptr(entity);
90 let total_armor = sum_armor(root_ptr);
91 println!("[Armor System] {} total armor: {}", name.0, total_armor);
92 }
93}
94
95fn main() {
96 let mut world = World::new();
97
98 println!("Building entity hierarchies...\n");
106
107 let a1 = world.spawn((Name("a1"), Health(50), Armor(20))).id();
109 let a2 = world.spawn((Name("a2"), Health(50), Armor(20))).id();
110 let alpha = world
111 .spawn((
112 Name("Squad Alpha"),
113 Health(100),
114 Armor(50),
115 RootMarker,
116 Children(vec![EntityHandle::new(a1), EntityHandle::new(a2)]),
117 ))
118 .id();
119
120 let b1 = world.spawn((Name("b1"), Health(40), Armor(15))).id();
122 let b2 = world.spawn((Name("b2"), Health(40), Armor(15))).id();
123 let _beta = world
124 .spawn((
125 Name("Squad Beta"),
126 Health(80),
127 Armor(30),
128 RootMarker,
129 Children(vec![EntityHandle::new(b1), EntityHandle::new(b2)]),
130 ))
131 .id();
132
133 println!("Simulating concurrent system execution:\n");
141 println!("(In a real Bevy app, these would run in parallel)\n");
142
143 let mut schedule = Schedule::default();
145 schedule.add_systems((compute_health_system, compute_armor_system));
146
147 schedule.run(&mut world);
149
150 println!("\n--- Verification ---");
152
153 let alpha_ptr = world.entity_ptr(alpha);
154
155 let alpha_health = sum_health(alpha_ptr);
156 let alpha_armor = sum_armor(alpha_ptr);
157
158 println!(
159 "Squad Alpha: health={}, armor={}",
160 alpha_health, alpha_armor
161 );
162 assert_eq!(alpha_health, 200); assert_eq!(alpha_armor, 90); println!("\nAll assertions passed!");
166 println!("\nKey takeaway: Use world.entity_ptr() in each system.");
167 println!("EntityPtr is NOT shared between systems - each system has");
168 println!("independent instances that are safe for concurrent reads.");
169}