bevy_ecs/observer/
mod.rs

1//! Observers are a push-based tool for responding to [`Event`]s. The [`Observer`] component holds a [`System`] that runs whenever a matching [`Event`]
2//! is triggered.
3//!
4//! See [`Event`] and [`Observer`] for in-depth documentation and usage examples.
5
6mod centralized_storage;
7mod distributed_storage;
8mod entity_cloning;
9mod runner;
10mod system_param;
11
12pub use centralized_storage::*;
13pub use distributed_storage::*;
14pub use runner::*;
15pub use system_param::*;
16
17use crate::{
18    change_detection::MaybeLocation,
19    event::Event,
20    prelude::*,
21    system::IntoObserverSystem,
22    world::{DeferredWorld, *},
23};
24
25impl World {
26    /// Spawns a "global" [`Observer`] which will watch for the given event.
27    /// Returns its [`Entity`] as a [`EntityWorldMut`].
28    ///
29    /// `system` can be any system whose first parameter is [`On`].
30    ///
31    /// # Example
32    ///
33    /// ```
34    /// # use bevy_ecs::prelude::*;
35    /// #[derive(Component)]
36    /// struct A;
37    ///
38    /// # let mut world = World::new();
39    /// world.add_observer(|_: On<Add, A>| {
40    ///     // ...
41    /// });
42    /// world.add_observer(|_: On<Remove, A>| {
43    ///     // ...
44    /// });
45    /// ```
46    ///
47    /// **Calling [`observe`](EntityWorldMut::observe) on the returned
48    /// [`EntityWorldMut`] will observe the observer itself, which you very
49    /// likely do not want.**
50    ///
51    /// # Panics
52    ///
53    /// Panics if the given system is an exclusive system.
54    pub fn add_observer<E: Event, B: Bundle, M>(
55        &mut self,
56        system: impl IntoObserverSystem<E, B, M>,
57    ) -> EntityWorldMut<'_> {
58        self.spawn(Observer::new(system))
59    }
60
61    /// Triggers the given [`Event`], which will run any [`Observer`]s watching for it.
62    ///
63    /// For a variant that borrows the `event` rather than consuming it, use [`World::trigger_ref`] instead.
64    #[track_caller]
65    pub fn trigger<'a, E: Event<Trigger<'a>: Default>>(&mut self, mut event: E) {
66        self.trigger_ref_with_caller(
67            &mut event,
68            &mut <E::Trigger<'a> as Default>::default(),
69            MaybeLocation::caller(),
70        );
71    }
72
73    /// A deprecated alias for [`trigger`](Self::trigger) to ease migration.
74    ///
75    /// Instead of specifying the trigger target separately,
76    /// information about the target of the event is embedded in the data held by
77    /// the event type itself.
78    #[deprecated(since = "0.17.0", note = "Use `World::trigger` instead.")]
79    pub fn trigger_targets<'a>(&mut self, event: impl Event<Trigger<'a>: Default>) {
80        self.trigger(event);
81    }
82
83    /// Triggers the given [`Event`] using the given [`Trigger`](crate::event::Trigger), which will run any [`Observer`]s watching for it.
84    ///
85    /// For a variant that borrows the `event` rather than consuming it, use [`World::trigger_ref`] instead.
86    #[track_caller]
87    pub fn trigger_with<'a, E: Event>(&mut self, mut event: E, mut trigger: E::Trigger<'a>) {
88        self.trigger_ref_with_caller(&mut event, &mut trigger, MaybeLocation::caller());
89    }
90
91    /// Triggers the given mutable [`Event`] reference, which will run any [`Observer`]s watching for it.
92    ///
93    /// Compared to [`World::trigger`], this method is most useful when it's necessary to check
94    /// or use the event after it has been modified by observers.
95    #[track_caller]
96    pub fn trigger_ref<'a, E: Event<Trigger<'a>: Default>>(&mut self, event: &mut E) {
97        self.trigger_ref_with_caller(
98            event,
99            &mut <E::Trigger<'a> as Default>::default(),
100            MaybeLocation::caller(),
101        );
102    }
103
104    /// Triggers the given mutable [`Event`] reference using the given mutable [`Trigger`](crate::event::Trigger) reference, which
105    /// will run any [`Observer`]s watching for it.
106    ///
107    /// Compared to [`World::trigger`], this method is most useful when it's necessary to check
108    /// or use the event after it has been modified by observers.
109    pub fn trigger_ref_with<'a, E: Event>(&mut self, event: &mut E, trigger: &mut E::Trigger<'a>) {
110        self.trigger_ref_with_caller(event, trigger, MaybeLocation::caller());
111    }
112
113    pub(crate) fn trigger_ref_with_caller<'a, E: Event>(
114        &mut self,
115        event: &mut E,
116        trigger: &mut E::Trigger<'a>,
117        caller: MaybeLocation,
118    ) {
119        let event_key = self.register_event_key::<E>();
120        // SAFETY: event_key was just registered and matches `event`
121        unsafe {
122            DeferredWorld::from(self).trigger_raw(event_key, event, trigger, caller);
123        }
124    }
125
126    /// Register an observer to the cache, called when an observer is created
127    pub(crate) fn register_observer(&mut self, observer_entity: Entity) {
128        // SAFETY: References do not alias.
129        let (observer_state, archetypes, observers) = unsafe {
130            let observer_state: *const Observer = self.get::<Observer>(observer_entity).unwrap();
131            // Populate ObservedBy for each observed entity.
132            for watched_entity in (*observer_state).descriptor.entities.iter().copied() {
133                let mut entity_mut = self.entity_mut(watched_entity);
134                let mut observed_by = entity_mut.entry::<ObservedBy>().or_default().into_mut();
135                observed_by.0.push(observer_entity);
136            }
137            (&*observer_state, &mut self.archetypes, &mut self.observers)
138        };
139        let descriptor = &observer_state.descriptor;
140
141        for &event_key in &descriptor.event_keys {
142            let cache = observers.get_observers_mut(event_key);
143
144            if descriptor.components.is_empty() && descriptor.entities.is_empty() {
145                cache
146                    .global_observers
147                    .insert(observer_entity, observer_state.runner);
148            } else if descriptor.components.is_empty() {
149                // Observer is not targeting any components so register it as an entity observer
150                for &watched_entity in &observer_state.descriptor.entities {
151                    let map = cache.entity_observers.entry(watched_entity).or_default();
152                    map.insert(observer_entity, observer_state.runner);
153                }
154            } else {
155                // Register observer for each watched component
156                for &component in &descriptor.components {
157                    let observers =
158                        cache
159                            .component_observers
160                            .entry(component)
161                            .or_insert_with(|| {
162                                if let Some(flag) = Observers::is_archetype_cached(event_key) {
163                                    archetypes.update_flags(component, flag, true);
164                                }
165                                CachedComponentObservers::default()
166                            });
167                    if descriptor.entities.is_empty() {
168                        // Register for all triggers targeting the component
169                        observers
170                            .global_observers
171                            .insert(observer_entity, observer_state.runner);
172                    } else {
173                        // Register for each watched entity
174                        for &watched_entity in &descriptor.entities {
175                            let map = observers
176                                .entity_component_observers
177                                .entry(watched_entity)
178                                .or_default();
179                            map.insert(observer_entity, observer_state.runner);
180                        }
181                    }
182                }
183            }
184        }
185    }
186
187    /// Remove the observer from the cache, called when an observer gets despawned
188    pub(crate) fn unregister_observer(&mut self, entity: Entity, descriptor: ObserverDescriptor) {
189        let archetypes = &mut self.archetypes;
190        let observers = &mut self.observers;
191
192        for &event_key in &descriptor.event_keys {
193            let cache = observers.get_observers_mut(event_key);
194            if descriptor.components.is_empty() && descriptor.entities.is_empty() {
195                cache.global_observers.remove(&entity);
196            } else if descriptor.components.is_empty() {
197                for watched_entity in &descriptor.entities {
198                    // This check should be unnecessary since this observer hasn't been unregistered yet
199                    let Some(observers) = cache.entity_observers.get_mut(watched_entity) else {
200                        continue;
201                    };
202                    observers.remove(&entity);
203                    if observers.is_empty() {
204                        cache.entity_observers.remove(watched_entity);
205                    }
206                }
207            } else {
208                for component in &descriptor.components {
209                    let Some(observers) = cache.component_observers.get_mut(component) else {
210                        continue;
211                    };
212                    if descriptor.entities.is_empty() {
213                        observers.global_observers.remove(&entity);
214                    } else {
215                        for watched_entity in &descriptor.entities {
216                            let Some(map) =
217                                observers.entity_component_observers.get_mut(watched_entity)
218                            else {
219                                continue;
220                            };
221                            map.remove(&entity);
222                            if map.is_empty() {
223                                observers.entity_component_observers.remove(watched_entity);
224                            }
225                        }
226                    }
227
228                    if observers.global_observers.is_empty()
229                        && observers.entity_component_observers.is_empty()
230                    {
231                        cache.component_observers.remove(component);
232                        if let Some(flag) = Observers::is_archetype_cached(event_key) {
233                            if let Some(by_component) = archetypes.by_component.get(component) {
234                                for archetype in by_component.keys() {
235                                    let archetype = &mut archetypes.archetypes[archetype.index()];
236                                    if archetype.contains(*component) {
237                                        let no_longer_observed = archetype
238                                            .iter_components()
239                                            .all(|id| !cache.component_observers.contains_key(&id));
240
241                                        if no_longer_observed {
242                                            archetype.flags.set(flag, false);
243                                        }
244                                    }
245                                }
246                            }
247                        }
248                    }
249                }
250            }
251        }
252    }
253}
254
255#[cfg(test)]
256mod tests {
257    use alloc::{vec, vec::Vec};
258
259    use bevy_ptr::OwningPtr;
260
261    use crate::{
262        change_detection::MaybeLocation,
263        entity_disabling::Internal,
264        event::{EntityComponentsTrigger, Event, GlobalTrigger},
265        hierarchy::ChildOf,
266        observer::{Observer, Replace},
267        prelude::*,
268        world::DeferredWorld,
269    };
270
271    #[derive(Component)]
272    struct A;
273
274    #[derive(Component)]
275    struct B;
276
277    #[derive(Component)]
278    #[component(storage = "SparseSet")]
279    struct S;
280
281    #[derive(Event)]
282    struct EventA;
283
284    #[derive(EntityEvent)]
285    struct EntityEventA(Entity);
286
287    #[derive(EntityEvent)]
288    #[entity_event(trigger = EntityComponentsTrigger<'a>)]
289    struct EntityComponentsEvent(Entity);
290
291    #[derive(Event)]
292    struct EventWithData {
293        counter: usize,
294    }
295
296    #[derive(Resource, Default)]
297    struct Order(Vec<&'static str>);
298
299    impl Order {
300        #[track_caller]
301        fn observed(&mut self, name: &'static str) {
302            self.0.push(name);
303        }
304    }
305
306    #[derive(Component, EntityEvent)]
307    #[entity_event(propagate, auto_propagate)]
308    struct EventPropagating(Entity);
309
310    #[test]
311    fn observer_order_spawn_despawn() {
312        let mut world = World::new();
313        world.init_resource::<Order>();
314
315        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
316        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
317        world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
318            res.observed("replace");
319        });
320        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
321
322        let entity = world.spawn(A).id();
323        world.despawn(entity);
324        assert_eq!(
325            vec!["add", "insert", "replace", "remove"],
326            world.resource::<Order>().0
327        );
328    }
329
330    #[test]
331    fn observer_order_insert_remove() {
332        let mut world = World::new();
333        world.init_resource::<Order>();
334
335        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
336        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
337        world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
338            res.observed("replace");
339        });
340        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
341
342        let mut entity = world.spawn_empty();
343        entity.insert(A);
344        entity.remove::<A>();
345        entity.flush();
346        assert_eq!(
347            vec!["add", "insert", "replace", "remove"],
348            world.resource::<Order>().0
349        );
350    }
351
352    #[test]
353    fn observer_order_insert_remove_sparse() {
354        let mut world = World::new();
355        world.init_resource::<Order>();
356
357        world.add_observer(|_: On<Add, S>, mut res: ResMut<Order>| res.observed("add"));
358        world.add_observer(|_: On<Insert, S>, mut res: ResMut<Order>| res.observed("insert"));
359        world.add_observer(|_: On<Replace, S>, mut res: ResMut<Order>| {
360            res.observed("replace");
361        });
362        world.add_observer(|_: On<Remove, S>, mut res: ResMut<Order>| res.observed("remove"));
363
364        let mut entity = world.spawn_empty();
365        entity.insert(S);
366        entity.remove::<S>();
367        entity.flush();
368        assert_eq!(
369            vec!["add", "insert", "replace", "remove"],
370            world.resource::<Order>().0
371        );
372    }
373
374    #[test]
375    fn observer_order_replace() {
376        let mut world = World::new();
377        world.init_resource::<Order>();
378
379        let entity = world.spawn(A).id();
380
381        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add"));
382        world.add_observer(|_: On<Insert, A>, mut res: ResMut<Order>| res.observed("insert"));
383        world.add_observer(|_: On<Replace, A>, mut res: ResMut<Order>| {
384            res.observed("replace");
385        });
386        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| res.observed("remove"));
387
388        let mut entity = world.entity_mut(entity);
389        entity.insert(A);
390        entity.flush();
391        assert_eq!(vec!["replace", "insert"], world.resource::<Order>().0);
392    }
393
394    #[test]
395    fn observer_order_recursive() {
396        let mut world = World::new();
397        world.init_resource::<Order>();
398        world.add_observer(
399            |add: On<Add, A>, mut res: ResMut<Order>, mut commands: Commands| {
400                res.observed("add_a");
401                commands.entity(add.entity).insert(B);
402            },
403        );
404        world.add_observer(
405            |remove: On<Remove, A>, mut res: ResMut<Order>, mut commands: Commands| {
406                res.observed("remove_a");
407                commands.entity(remove.entity).remove::<B>();
408            },
409        );
410
411        world.add_observer(
412            |add: On<Add, B>, mut res: ResMut<Order>, mut commands: Commands| {
413                res.observed("add_b");
414                commands.entity(add.entity).remove::<A>();
415            },
416        );
417        world.add_observer(|_: On<Remove, B>, mut res: ResMut<Order>| {
418            res.observed("remove_b");
419        });
420
421        let entity = world.spawn(A).flush();
422        let entity = world.get_entity(entity).unwrap();
423        assert!(!entity.contains::<A>());
424        assert!(!entity.contains::<B>());
425        assert_eq!(
426            vec!["add_a", "add_b", "remove_a", "remove_b"],
427            world.resource::<Order>().0
428        );
429    }
430
431    #[test]
432    fn observer_trigger_ref() {
433        let mut world = World::new();
434
435        world.add_observer(|mut event: On<EventWithData>| event.counter += 1);
436        world.add_observer(|mut event: On<EventWithData>| event.counter += 2);
437        world.add_observer(|mut event: On<EventWithData>| event.counter += 4);
438
439        let mut event = EventWithData { counter: 0 };
440        world.trigger_ref(&mut event);
441        assert_eq!(7, event.counter);
442    }
443
444    #[test]
445    fn observer_multiple_listeners() {
446        let mut world = World::new();
447        world.init_resource::<Order>();
448
449        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_1"));
450        world.add_observer(|_: On<Add, A>, mut res: ResMut<Order>| res.observed("add_2"));
451
452        world.spawn(A).flush();
453        assert_eq!(vec!["add_2", "add_1"], world.resource::<Order>().0);
454        // we have one A entity and two observers
455        assert_eq!(world.query::<&A>().query(&world).count(), 1);
456        assert_eq!(
457            world
458                .query_filtered::<&Observer, Allow<Internal>>()
459                .query(&world)
460                .count(),
461            2
462        );
463    }
464
465    #[test]
466    fn observer_multiple_events() {
467        let mut world = World::new();
468        world.init_resource::<Order>();
469        let on_remove = world.register_event_key::<Remove>();
470        world.spawn(
471            // SAFETY: Add and Remove are both unit types, so this is safe
472            unsafe {
473                Observer::new(|_: On<Add, A>, mut res: ResMut<Order>| {
474                    res.observed("add/remove");
475                })
476                .with_event_key(on_remove)
477            },
478        );
479
480        let entity = world.spawn(A).id();
481        world.despawn(entity);
482        assert_eq!(
483            vec!["add/remove", "add/remove"],
484            world.resource::<Order>().0
485        );
486    }
487
488    #[test]
489    fn observer_multiple_components() {
490        let mut world = World::new();
491        world.init_resource::<Order>();
492        world.register_component::<A>();
493        world.register_component::<B>();
494
495        world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
496            res.observed("add_ab");
497        });
498
499        let entity = world.spawn(A).id();
500        world.entity_mut(entity).insert(B);
501        assert_eq!(vec!["add_ab", "add_ab"], world.resource::<Order>().0);
502    }
503
504    #[test]
505    fn observer_despawn() {
506        let mut world = World::new();
507
508        let system: fn(On<Add, A>) = |_| {
509            panic!("Observer triggered after being despawned.");
510        };
511        let observer = world.add_observer(system).id();
512        world.despawn(observer);
513        world.spawn(A).flush();
514    }
515
516    // Regression test for https://github.com/bevyengine/bevy/issues/14961
517    #[test]
518    fn observer_despawn_archetype_flags() {
519        let mut world = World::new();
520        world.init_resource::<Order>();
521
522        let entity = world.spawn((A, B)).flush();
523
524        world.add_observer(|_: On<Remove, A>, mut res: ResMut<Order>| {
525            res.observed("remove_a");
526        });
527
528        let system: fn(On<Remove, B>) = |_: On<Remove, B>| {
529            panic!("Observer triggered after being despawned.");
530        };
531
532        let observer = world.add_observer(system).flush();
533        world.despawn(observer);
534
535        world.despawn(entity);
536
537        assert_eq!(vec!["remove_a"], world.resource::<Order>().0);
538    }
539
540    #[test]
541    fn observer_multiple_matches() {
542        let mut world = World::new();
543        world.init_resource::<Order>();
544
545        world.add_observer(|_: On<Add, (A, B)>, mut res: ResMut<Order>| {
546            res.observed("add_ab");
547        });
548
549        world.spawn((A, B)).flush();
550        assert_eq!(vec!["add_ab"], world.resource::<Order>().0);
551    }
552
553    #[test]
554    fn observer_entity_routing() {
555        let mut world = World::new();
556        world.init_resource::<Order>();
557
558        let system: fn(On<EntityEventA>) = |_| {
559            panic!("Trigger routed to non-targeted entity.");
560        };
561
562        world.spawn_empty().observe(system);
563        let entity = world
564            .spawn_empty()
565            .observe(|_: On<EntityEventA>, mut res: ResMut<Order>| res.observed("a_1"))
566            .id();
567        world.add_observer(move |event: On<EntityEventA>, mut res: ResMut<Order>| {
568            assert_eq!(event.event_target(), entity);
569            res.observed("a_2");
570        });
571
572        world.trigger(EntityEventA(entity));
573        assert_eq!(vec!["a_2", "a_1"], world.resource::<Order>().0);
574    }
575
576    #[test]
577    fn observer_multiple_targets() {
578        #[derive(Resource, Default)]
579        struct R(i32);
580
581        let mut world = World::new();
582        let component_a = world.register_component::<A>();
583        let component_b = world.register_component::<B>();
584        world.init_resource::<R>();
585
586        // targets (entity_1, A)
587        let entity_1 = world
588            .spawn_empty()
589            .observe(|_: On<EntityComponentsEvent, A>, mut res: ResMut<R>| res.0 += 1)
590            .id();
591        // targets (entity_2, B)
592        let entity_2 = world
593            .spawn_empty()
594            .observe(|_: On<EntityComponentsEvent, B>, mut res: ResMut<R>| res.0 += 10)
595            .id();
596        // targets any entity or component
597        world.add_observer(|_: On<EntityComponentsEvent>, mut res: ResMut<R>| res.0 += 100);
598        // targets any entity, and components A or B
599        world
600            .add_observer(|_: On<EntityComponentsEvent, (A, B)>, mut res: ResMut<R>| res.0 += 1000);
601        // test all tuples
602        world.add_observer(
603            |_: On<EntityComponentsEvent, (A, B, (A, B))>, mut res: ResMut<R>| res.0 += 10000,
604        );
605        world.add_observer(
606            |_: On<EntityComponentsEvent, (A, B, (A, B), ((A, B), (A, B)))>, mut res: ResMut<R>| {
607                res.0 += 100000;
608            },
609        );
610        world.add_observer(
611            |_: On<EntityComponentsEvent, (A, B, (A, B), (B, A), (A, B, ((A, B), (B, A))))>,
612             mut res: ResMut<R>| res.0 += 1000000,
613        );
614
615        // trigger for an entity and a component
616        world.trigger_with(
617            EntityComponentsEvent(entity_1),
618            EntityComponentsTrigger {
619                components: &[component_a],
620            },
621        );
622        // only observer that doesn't trigger is the one only watching entity_2
623        assert_eq!(1111101, world.resource::<R>().0);
624        world.resource_mut::<R>().0 = 0;
625
626        // trigger for both entities, but no components: trigger once per entity target
627        world.trigger_with(
628            EntityComponentsEvent(entity_1),
629            EntityComponentsTrigger { components: &[] },
630        );
631        world.trigger_with(
632            EntityComponentsEvent(entity_2),
633            EntityComponentsTrigger { components: &[] },
634        );
635
636        // only the observer that doesn't require components triggers - once per entity
637        assert_eq!(200, world.resource::<R>().0);
638        world.resource_mut::<R>().0 = 0;
639
640        // trigger for both entities and both components: trigger once per entity target
641        // we only get 2222211 because a given observer can trigger only once per entity target
642        world.trigger_with(
643            EntityComponentsEvent(entity_1),
644            EntityComponentsTrigger {
645                components: &[component_a, component_b],
646            },
647        );
648        world.trigger_with(
649            EntityComponentsEvent(entity_2),
650            EntityComponentsTrigger {
651                components: &[component_a, component_b],
652            },
653        );
654        assert_eq!(2222211, world.resource::<R>().0);
655        world.resource_mut::<R>().0 = 0;
656    }
657
658    #[test]
659    fn observer_dynamic_component() {
660        let mut world = World::new();
661        world.init_resource::<Order>();
662
663        let component_id = world.register_component::<A>();
664        world.spawn(
665            Observer::new(|_: On<Add>, mut res: ResMut<Order>| res.observed("event_a"))
666                .with_component(component_id),
667        );
668
669        let mut entity = world.spawn_empty();
670        OwningPtr::make(A, |ptr| {
671            // SAFETY: we registered `component_id` above.
672            unsafe { entity.insert_by_id(component_id, ptr) };
673        });
674
675        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
676    }
677
678    #[test]
679    fn observer_dynamic_trigger() {
680        let mut world = World::new();
681        world.init_resource::<Order>();
682        let event_a = world.register_event_key::<EventA>();
683
684        // SAFETY: we registered `event_a` above and it matches the type of EventA
685        let observe = unsafe {
686            Observer::with_dynamic_runner(
687                |mut world, _observer, _trigger_context, _event, _trigger| {
688                    world.resource_mut::<Order>().observed("event_a");
689                },
690            )
691            .with_event_key(event_a)
692        };
693        world.spawn(observe);
694
695        world.commands().queue(move |world: &mut World| {
696            // SAFETY: we registered `event_a` above and it matches the type of EventA
697            unsafe {
698                DeferredWorld::from(world).trigger_raw(
699                    event_a,
700                    &mut EventA,
701                    &mut GlobalTrigger,
702                    MaybeLocation::caller(),
703                );
704            }
705        });
706        world.flush();
707        assert_eq!(vec!["event_a"], world.resource::<Order>().0);
708    }
709
710    #[test]
711    fn observer_propagating() {
712        let mut world = World::new();
713        world.init_resource::<Order>();
714
715        let parent = world.spawn_empty().id();
716        let child = world.spawn(ChildOf(parent)).id();
717
718        world.entity_mut(parent).observe(
719            move |event: On<EventPropagating>, mut res: ResMut<Order>| {
720                res.observed("parent");
721
722                assert_eq!(event.event_target(), parent);
723                assert_eq!(event.original_event_target(), child);
724            },
725        );
726
727        world.entity_mut(child).observe(
728            move |event: On<EventPropagating>, mut res: ResMut<Order>| {
729                res.observed("child");
730                assert_eq!(event.event_target(), child);
731                assert_eq!(event.original_event_target(), child);
732            },
733        );
734
735        world.trigger(EventPropagating(child));
736
737        assert_eq!(vec!["child", "parent"], world.resource::<Order>().0);
738    }
739
740    #[test]
741    fn observer_propagating_redundant_dispatch_same_entity() {
742        let mut world = World::new();
743        world.init_resource::<Order>();
744
745        let parent = world
746            .spawn_empty()
747            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
748                res.observed("parent");
749            })
750            .id();
751
752        let child = world
753            .spawn(ChildOf(parent))
754            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
755                res.observed("child");
756            })
757            .id();
758
759        world.trigger(EventPropagating(child));
760        world.trigger(EventPropagating(child));
761
762        assert_eq!(
763            vec!["child", "parent", "child", "parent"],
764            world.resource::<Order>().0
765        );
766    }
767
768    #[test]
769    fn observer_propagating_redundant_dispatch_parent_child() {
770        let mut world = World::new();
771        world.init_resource::<Order>();
772
773        let parent = world
774            .spawn_empty()
775            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
776                res.observed("parent");
777            })
778            .id();
779
780        let child = world
781            .spawn(ChildOf(parent))
782            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
783                res.observed("child");
784            })
785            .id();
786
787        world.trigger(EventPropagating(child));
788        world.trigger(EventPropagating(parent));
789
790        assert_eq!(
791            vec!["child", "parent", "parent"],
792            world.resource::<Order>().0
793        );
794    }
795
796    #[test]
797    fn observer_propagating_halt() {
798        let mut world = World::new();
799        world.init_resource::<Order>();
800
801        let parent = world
802            .spawn_empty()
803            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
804                res.observed("parent");
805            })
806            .id();
807
808        let child = world
809            .spawn(ChildOf(parent))
810            .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
811                res.observed("child");
812                event.propagate(false);
813            })
814            .id();
815
816        world.trigger(EventPropagating(child));
817
818        assert_eq!(vec!["child"], world.resource::<Order>().0);
819    }
820
821    #[test]
822    fn observer_propagating_join() {
823        let mut world = World::new();
824        world.init_resource::<Order>();
825
826        let parent = world
827            .spawn_empty()
828            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
829                res.observed("parent");
830            })
831            .id();
832
833        let child_a = world
834            .spawn(ChildOf(parent))
835            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
836                res.observed("child_a");
837            })
838            .id();
839
840        let child_b = world
841            .spawn(ChildOf(parent))
842            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
843                res.observed("child_b");
844            })
845            .id();
846
847        world.trigger(EventPropagating(child_a));
848        world.trigger(EventPropagating(child_b));
849
850        assert_eq!(
851            vec!["child_a", "parent", "child_b", "parent"],
852            world.resource::<Order>().0
853        );
854    }
855
856    #[test]
857    fn observer_propagating_no_next() {
858        let mut world = World::new();
859        world.init_resource::<Order>();
860
861        let entity = world
862            .spawn_empty()
863            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
864                res.observed("event");
865            })
866            .id();
867
868        world.trigger(EventPropagating(entity));
869        assert_eq!(vec!["event"], world.resource::<Order>().0);
870    }
871
872    #[test]
873    fn observer_propagating_parallel_propagation() {
874        let mut world = World::new();
875        world.init_resource::<Order>();
876
877        let parent_a = world
878            .spawn_empty()
879            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
880                res.observed("parent_a");
881            })
882            .id();
883
884        let child_a = world
885            .spawn(ChildOf(parent_a))
886            .observe(|mut event: On<EventPropagating>, mut res: ResMut<Order>| {
887                res.observed("child_a");
888                event.propagate(false);
889            })
890            .id();
891
892        let parent_b = world
893            .spawn_empty()
894            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
895                res.observed("parent_b");
896            })
897            .id();
898
899        let child_b = world
900            .spawn(ChildOf(parent_b))
901            .observe(|_: On<EventPropagating>, mut res: ResMut<Order>| {
902                res.observed("child_b");
903            })
904            .id();
905
906        world.trigger(EventPropagating(child_a));
907        world.trigger(EventPropagating(child_b));
908
909        assert_eq!(
910            vec!["child_a", "child_b", "parent_b"],
911            world.resource::<Order>().0
912        );
913    }
914
915    #[test]
916    fn observer_propagating_world() {
917        let mut world = World::new();
918        world.init_resource::<Order>();
919
920        world.add_observer(|_: On<EventPropagating>, mut res: ResMut<Order>| {
921            res.observed("event");
922        });
923
924        let grandparent = world.spawn_empty().id();
925        let parent = world.spawn(ChildOf(grandparent)).id();
926        let child = world.spawn(ChildOf(parent)).id();
927
928        world.trigger(EventPropagating(child));
929
930        assert_eq!(vec!["event", "event", "event"], world.resource::<Order>().0);
931    }
932
933    #[test]
934    fn observer_propagating_world_skipping() {
935        let mut world = World::new();
936        world.init_resource::<Order>();
937
938        world.add_observer(
939            |event: On<EventPropagating>, query: Query<&A>, mut res: ResMut<Order>| {
940                if query.get(event.event_target()).is_ok() {
941                    res.observed("event");
942                }
943            },
944        );
945
946        let grandparent = world.spawn(A).id();
947        let parent = world.spawn(ChildOf(grandparent)).id();
948        let child = world.spawn((A, ChildOf(parent))).id();
949
950        world.trigger(EventPropagating(child));
951
952        assert_eq!(vec!["event", "event"], world.resource::<Order>().0);
953    }
954
955    // Originally for https://github.com/bevyengine/bevy/issues/18452
956    #[test]
957    fn observer_modifies_relationship() {
958        fn on_add(add: On<Add, A>, mut commands: Commands) {
959            commands
960                .entity(add.entity)
961                .with_related_entities::<crate::hierarchy::ChildOf>(|rsc| {
962                    rsc.spawn_empty();
963                });
964        }
965
966        let mut world = World::new();
967        world.add_observer(on_add);
968        world.spawn(A);
969    }
970
971    // Regression test for https://github.com/bevyengine/bevy/issues/14467
972    // Fails prior to https://github.com/bevyengine/bevy/pull/15398
973    #[test]
974    fn observer_on_remove_during_despawn_spawn_empty() {
975        let mut world = World::new();
976
977        // Observe the removal of A - this will run during despawn
978        world.add_observer(|_: On<Remove, A>, mut cmd: Commands| {
979            // Spawn a new entity - this reserves a new ID and requires a flush
980            // afterward before Entities::free can be called.
981            cmd.spawn_empty();
982        });
983
984        let ent = world.spawn(A).id();
985
986        // Despawn our entity, which runs the Remove observer and allocates a
987        // new Entity.
988        // Should not panic - if it does, then Entities was not flushed properly
989        // after the observer's spawn_empty.
990        world.despawn(ent);
991    }
992
993    #[test]
994    #[should_panic]
995    fn observer_invalid_params() {
996        #[derive(Resource)]
997        struct ResA;
998
999        #[derive(Resource)]
1000        struct ResB;
1001
1002        let mut world = World::new();
1003        // This fails because `ResA` is not present in the world
1004        world.add_observer(|_: On<EventA>, _: Res<ResA>, mut commands: Commands| {
1005            commands.insert_resource(ResB);
1006        });
1007        world.trigger(EventA);
1008    }
1009
1010    #[test]
1011    fn observer_apply_deferred_from_param_set() {
1012        #[derive(Resource)]
1013        struct ResA;
1014
1015        let mut world = World::new();
1016        world.add_observer(
1017            |_: On<EventA>, mut params: ParamSet<(Query<Entity>, Commands)>| {
1018                params.p1().insert_resource(ResA);
1019            },
1020        );
1021
1022        world.trigger(EventA);
1023        world.flush();
1024
1025        assert!(world.get_resource::<ResA>().is_some());
1026    }
1027
1028    #[test]
1029    #[track_caller]
1030    fn observer_caller_location_event() {
1031        #[derive(Event)]
1032        struct EventA;
1033
1034        let caller = MaybeLocation::caller();
1035        let mut world = World::new();
1036        world.add_observer(move |event: On<EventA>| {
1037            assert_eq!(event.caller(), caller);
1038        });
1039        world.trigger(EventA);
1040    }
1041
1042    #[test]
1043    #[track_caller]
1044    fn observer_caller_location_command_archetype_move() {
1045        #[derive(Component)]
1046        struct Component;
1047
1048        let caller = MaybeLocation::caller();
1049        let mut world = World::new();
1050        world.add_observer(move |event: On<Add, Component>| {
1051            assert_eq!(event.caller(), caller);
1052        });
1053        world.add_observer(move |event: On<Remove, Component>| {
1054            assert_eq!(event.caller(), caller);
1055        });
1056        world.commands().spawn(Component).clear();
1057    }
1058
1059    #[test]
1060    fn observer_watch_entities() {
1061        let mut world = World::new();
1062        world.init_resource::<Order>();
1063        let entities = world
1064            .spawn_batch(core::iter::repeat_n((), 4))
1065            .collect::<Vec<_>>();
1066        let observer = Observer::new(|_: On<EntityEventA>, mut order: ResMut<Order>| {
1067            order.observed("a");
1068        });
1069        world.spawn(observer.with_entities(entities.iter().copied().take(2)));
1070
1071        world.trigger(EntityEventA(entities[0]));
1072        world.trigger(EntityEventA(entities[1]));
1073        assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1074        world.trigger(EntityEventA(entities[2]));
1075        world.trigger(EntityEventA(entities[3]));
1076        assert_eq!(vec!["a", "a"], world.resource::<Order>().0);
1077    }
1078
1079    #[test]
1080    fn unregister_global_observer() {
1081        let mut world = World::new();
1082        let mut observer = world.add_observer(|_: On<EventA>| {});
1083        observer.remove::<Observer>();
1084        let id = observer.id();
1085        let event_key = world.event_key::<EventA>().unwrap();
1086        assert!(!world
1087            .observers
1088            .get_observers_mut(event_key)
1089            .global_observers
1090            .contains_key(&id));
1091    }
1092
1093    #[test]
1094    fn unregister_entity_observer() {
1095        let mut world = World::new();
1096        let entity = world.spawn_empty().id();
1097        let observer = Observer::new(|_: On<EventA>| {}).with_entity(entity);
1098        let mut observer = world.spawn(observer);
1099        observer.remove::<Observer>();
1100        let event_key = world.event_key::<EventA>().unwrap();
1101        assert!(!world
1102            .observers
1103            .get_observers_mut(event_key)
1104            .entity_observers
1105            .contains_key(&entity));
1106    }
1107
1108    #[test]
1109    fn unregister_component_observer() {
1110        let mut world = World::new();
1111        let a = world.register_component::<A>();
1112        let observer = Observer::new(|_: On<EventA>| {}).with_component(a);
1113        let mut observer = world.spawn(observer);
1114        observer.remove::<Observer>();
1115        let event_key = world.event_key::<EventA>().unwrap();
1116        assert!(!world
1117            .observers
1118            .get_observers_mut(event_key)
1119            .component_observers()
1120            .contains_key(&a));
1121    }
1122
1123    #[test]
1124    #[expect(deprecated, reason = "We still need to test `On::target`")]
1125    fn observer_target() {
1126        let mut world = World::new();
1127        let entity = world
1128            .spawn_empty()
1129            .observe(|event: On<EntityEventA>| {
1130                assert_eq!(event.target(), event.event_target());
1131            })
1132            .id();
1133        world.trigger(EntityEventA(entity));
1134    }
1135}