bevy_ecs/observer/
runner.rs

1use alloc::{boxed::Box, vec, vec::Vec};
2use core::any::Any;
3
4use crate::{
5    component::{ComponentHook, ComponentId, HookContext, Mutable, StorageType},
6    error::{default_error_handler, ErrorContext},
7    observer::{ObserverDescriptor, ObserverTrigger},
8    prelude::*,
9    query::DebugCheckedUnwrap,
10    system::{IntoObserverSystem, ObserverSystem},
11    world::DeferredWorld,
12};
13use bevy_ptr::PtrMut;
14
15/// Contains [`Observer`] information. This defines how a given observer behaves. It is the
16/// "source of truth" for a given observer entity's behavior.
17pub struct ObserverState {
18    pub(crate) descriptor: ObserverDescriptor,
19    pub(crate) runner: ObserverRunner,
20    pub(crate) last_trigger_id: u32,
21    pub(crate) despawned_watched_entities: u32,
22}
23
24impl Default for ObserverState {
25    fn default() -> Self {
26        Self {
27            runner: |_, _, _, _| {},
28            last_trigger_id: 0,
29            despawned_watched_entities: 0,
30            descriptor: Default::default(),
31        }
32    }
33}
34
35impl ObserverState {
36    /// Observe the given `event`. This will cause the [`Observer`] to run whenever an event with the given [`ComponentId`]
37    /// is triggered.
38    pub fn with_event(mut self, event: ComponentId) -> Self {
39        self.descriptor.events.push(event);
40        self
41    }
42
43    /// Observe the given event list. This will cause the [`Observer`] to run whenever an event with any of the given [`ComponentId`]s
44    /// is triggered.
45    pub fn with_events(mut self, events: impl IntoIterator<Item = ComponentId>) -> Self {
46        self.descriptor.events.extend(events);
47        self
48    }
49
50    /// Observe the given [`Entity`] list. This will cause the [`Observer`] to run whenever the [`Event`] is triggered
51    /// for any [`Entity`] target in the list.
52    pub fn with_entities(mut self, entities: impl IntoIterator<Item = Entity>) -> Self {
53        self.descriptor.entities.extend(entities);
54        self
55    }
56
57    /// Observe the given [`ComponentId`] list. This will cause the [`Observer`] to run whenever the [`Event`] is triggered
58    /// for any [`ComponentId`] target in the list.
59    pub fn with_components(mut self, components: impl IntoIterator<Item = ComponentId>) -> Self {
60        self.descriptor.components.extend(components);
61        self
62    }
63}
64
65impl Component for ObserverState {
66    const STORAGE_TYPE: StorageType = StorageType::SparseSet;
67    type Mutability = Mutable;
68
69    fn on_add() -> Option<ComponentHook> {
70        Some(|mut world, HookContext { entity, .. }| {
71            world.commands().queue(move |world: &mut World| {
72                world.register_observer(entity);
73            });
74        })
75    }
76
77    fn on_remove() -> Option<ComponentHook> {
78        Some(|mut world, HookContext { entity, .. }| {
79            let descriptor = core::mem::take(
80                &mut world
81                    .entity_mut(entity)
82                    .get_mut::<ObserverState>()
83                    .unwrap()
84                    .as_mut()
85                    .descriptor,
86            );
87            world.commands().queue(move |world: &mut World| {
88                world.unregister_observer(entity, descriptor);
89            });
90        })
91    }
92}
93
94/// Type for function that is run when an observer is triggered.
95///
96/// Typically refers to the default runner that runs the system stored in the associated [`Observer`] component,
97/// but can be overridden for custom behavior.
98pub type ObserverRunner = fn(DeferredWorld, ObserverTrigger, PtrMut, propagate: &mut bool);
99
100/// An [`Observer`] system. Add this [`Component`] to an [`Entity`] to turn it into an "observer".
101///
102/// Observers listen for a "trigger" of a specific [`Event`]. Events are triggered by calling [`World::trigger`] or [`World::trigger_targets`].
103///
104/// Note that "buffered" events sent using [`EventReader`] and [`EventWriter`] are _not_ automatically triggered. They must be triggered at a specific
105/// point in the schedule.
106///
107/// # Usage
108///
109/// The simplest usage
110/// of the observer pattern looks like this:
111///
112/// ```
113/// # use bevy_ecs::prelude::*;
114/// # let mut world = World::default();
115/// #[derive(Event)]
116/// struct Speak {
117///     message: String,
118/// }
119///
120/// world.add_observer(|trigger: Trigger<Speak>| {
121///     println!("{}", trigger.event().message);
122/// });
123///
124/// // Observers currently require a flush() to be registered. In the context of schedules,
125/// // this will generally be done for you.
126/// world.flush();
127///
128/// world.trigger(Speak {
129///     message: "Hello!".into(),
130/// });
131/// ```
132///
133/// Notice that we used [`World::add_observer`]. This is just a shorthand for spawning an [`Observer`] manually:
134///
135/// ```
136/// # use bevy_ecs::prelude::*;
137/// # let mut world = World::default();
138/// # #[derive(Event)]
139/// # struct Speak;
140/// // These are functionally the same:
141/// world.add_observer(|trigger: Trigger<Speak>| {});
142/// world.spawn(Observer::new(|trigger: Trigger<Speak>| {}));
143/// ```
144///
145/// Observers are systems. They can access arbitrary [`World`] data by adding [`SystemParam`]s:
146///
147/// ```
148/// # use bevy_ecs::prelude::*;
149/// # let mut world = World::default();
150/// # #[derive(Event)]
151/// # struct PrintNames;
152/// # #[derive(Component, Debug)]
153/// # struct Name;
154/// world.add_observer(|trigger: Trigger<PrintNames>, names: Query<&Name>| {
155///     for name in &names {
156///         println!("{name:?}");
157///     }
158/// });
159/// ```
160///
161/// Note that [`Trigger`] must always be the first parameter.
162///
163/// You can also add [`Commands`], which means you can spawn new entities, insert new components, etc:
164///
165/// ```
166/// # use bevy_ecs::prelude::*;
167/// # let mut world = World::default();
168/// # #[derive(Event)]
169/// # struct SpawnThing;
170/// # #[derive(Component, Debug)]
171/// # struct Thing;
172/// world.add_observer(|trigger: Trigger<SpawnThing>, mut commands: Commands| {
173///     commands.spawn(Thing);
174/// });
175/// ```
176///
177/// Observers can also trigger new events:
178///
179/// ```
180/// # use bevy_ecs::prelude::*;
181/// # let mut world = World::default();
182/// # #[derive(Event)]
183/// # struct A;
184/// # #[derive(Event)]
185/// # struct B;
186/// world.add_observer(|trigger: Trigger<A>, mut commands: Commands| {
187///     commands.trigger(B);
188/// });
189/// ```
190///
191/// When the commands are flushed (including these "nested triggers") they will be
192/// recursively evaluated until there are no commands left, meaning nested triggers all
193/// evaluate at the same time!
194///
195/// Events can be triggered for entities, which will be passed to the [`Observer`]:
196///
197/// ```
198/// # use bevy_ecs::prelude::*;
199/// # let mut world = World::default();
200/// # let entity = world.spawn_empty().id();
201/// #[derive(Event)]
202/// struct Explode;
203///
204/// world.add_observer(|trigger: Trigger<Explode>, mut commands: Commands| {
205///     println!("Entity {} goes BOOM!", trigger.target());
206///     commands.entity(trigger.target()).despawn();
207/// });
208///
209/// world.flush();
210///
211/// world.trigger_targets(Explode, entity);
212/// ```
213///
214/// You can trigger multiple entities at once:
215///
216/// ```
217/// # use bevy_ecs::prelude::*;
218/// # let mut world = World::default();
219/// # let e1 = world.spawn_empty().id();
220/// # let e2 = world.spawn_empty().id();
221/// # #[derive(Event)]
222/// # struct Explode;
223/// world.trigger_targets(Explode, [e1, e2]);
224/// ```
225///
226/// Observers can also watch _specific_ entities, which enables you to assign entity-specific logic:
227///
228/// ```
229/// # use bevy_ecs::prelude::*;
230/// # #[derive(Component, Debug)]
231/// # struct Name(String);
232/// # let mut world = World::default();
233/// # let e1 = world.spawn_empty().id();
234/// # let e2 = world.spawn_empty().id();
235/// # #[derive(Event)]
236/// # struct Explode;
237/// world.entity_mut(e1).observe(|trigger: Trigger<Explode>, mut commands: Commands| {
238///     println!("Boom!");
239///     commands.entity(trigger.target()).despawn();
240/// });
241///
242/// world.entity_mut(e2).observe(|trigger: Trigger<Explode>, mut commands: Commands| {
243///     println!("The explosion fizzles! This entity is immune!");
244/// });
245/// ```
246///
247/// If all entities watched by a given [`Observer`] are despawned, the [`Observer`] entity will also be despawned.
248/// This protects against observer "garbage" building up over time.
249///
250/// The examples above calling [`EntityWorldMut::observe`] to add entity-specific observer logic are (once again)
251/// just shorthand for spawning an [`Observer`] directly:
252///
253/// ```
254/// # use bevy_ecs::prelude::*;
255/// # let mut world = World::default();
256/// # let entity = world.spawn_empty().id();
257/// # #[derive(Event)]
258/// # struct Explode;
259/// let mut observer = Observer::new(|trigger: Trigger<Explode>| {});
260/// observer.watch_entity(entity);
261/// world.spawn(observer);
262/// ```
263///
264/// Note that the [`Observer`] component is not added to the entity it is observing. Observers should always be their own entities!
265///
266/// You can call [`Observer::watch_entity`] more than once, which allows you to watch multiple entities with the same [`Observer`].
267///
268/// When first added, [`Observer`] will also create an [`ObserverState`] component, which registers the observer with the [`World`] and
269/// serves as the "source of truth" of the observer.
270///
271/// [`SystemParam`]: crate::system::SystemParam
272pub struct Observer {
273    system: Box<dyn Any + Send + Sync + 'static>,
274    descriptor: ObserverDescriptor,
275    hook_on_add: ComponentHook,
276    error_handler: Option<fn(BevyError, ErrorContext)>,
277}
278
279impl Observer {
280    /// Creates a new [`Observer`], which defaults to a "global" observer. This means it will run whenever the event `E` is triggered
281    /// for _any_ entity (or no entity).
282    pub fn new<E: Event, B: Bundle, M, I: IntoObserverSystem<E, B, M>>(system: I) -> Self {
283        Self {
284            system: Box::new(IntoObserverSystem::into_system(system)),
285            descriptor: Default::default(),
286            hook_on_add: hook_on_add::<E, B, I::System>,
287            error_handler: None,
288        }
289    }
290
291    /// Observe the given `entity`. This will cause the [`Observer`] to run whenever the [`Event`] is triggered
292    /// for the `entity`.
293    pub fn with_entity(mut self, entity: Entity) -> Self {
294        self.descriptor.entities.push(entity);
295        self
296    }
297
298    /// Observe the given `entity`. This will cause the [`Observer`] to run whenever the [`Event`] is triggered
299    /// for the `entity`.
300    /// Note that if this is called _after_ an [`Observer`] is spawned, it will produce no effects.
301    pub fn watch_entity(&mut self, entity: Entity) {
302        self.descriptor.entities.push(entity);
303    }
304
305    /// Observe the given `component`. This will cause the [`Observer`] to run whenever the [`Event`] is triggered
306    /// with the given component target.
307    pub fn with_component(mut self, component: ComponentId) -> Self {
308        self.descriptor.components.push(component);
309        self
310    }
311
312    /// Observe the given `event`. This will cause the [`Observer`] to run whenever an event with the given [`ComponentId`]
313    /// is triggered.
314    /// # Safety
315    /// The type of the `event` [`ComponentId`] _must_ match the actual value
316    /// of the event passed into the observer system.
317    pub unsafe fn with_event(mut self, event: ComponentId) -> Self {
318        self.descriptor.events.push(event);
319        self
320    }
321
322    /// Set the error handler to use for this observer.
323    ///
324    /// See the [`error` module-level documentation](crate::error) for more information.
325    pub fn with_error_handler(mut self, error_handler: fn(BevyError, ErrorContext)) -> Self {
326        self.error_handler = Some(error_handler);
327        self
328    }
329
330    /// Returns the [`ObserverDescriptor`] for this [`Observer`].
331    pub fn descriptor(&self) -> &ObserverDescriptor {
332        &self.descriptor
333    }
334}
335
336impl Component for Observer {
337    const STORAGE_TYPE: StorageType = StorageType::SparseSet;
338    type Mutability = Mutable;
339    fn on_add() -> Option<ComponentHook> {
340        Some(|world, context| {
341            let Some(observe) = world.get::<Self>(context.entity) else {
342                return;
343            };
344            let hook = observe.hook_on_add;
345            hook(world, context);
346        })
347    }
348}
349
350fn observer_system_runner<E: Event, B: Bundle, S: ObserverSystem<E, B>>(
351    mut world: DeferredWorld,
352    observer_trigger: ObserverTrigger,
353    ptr: PtrMut,
354    propagate: &mut bool,
355) {
356    let world = world.as_unsafe_world_cell();
357    // SAFETY: Observer was triggered so must still exist in world
358    let observer_cell = unsafe {
359        world
360            .get_entity(observer_trigger.observer)
361            .debug_checked_unwrap()
362    };
363    // SAFETY: Observer was triggered so must have an `ObserverState`
364    let mut state = unsafe {
365        observer_cell
366            .get_mut::<ObserverState>()
367            .debug_checked_unwrap()
368    };
369
370    // TODO: Move this check into the observer cache to avoid dynamic dispatch
371    let last_trigger = world.last_trigger_id();
372    if state.last_trigger_id == last_trigger {
373        return;
374    }
375    state.last_trigger_id = last_trigger;
376
377    // SAFETY: Observer was triggered so must have an `Observer` component.
378    let error_handler = unsafe {
379        observer_cell
380            .get::<Observer>()
381            .debug_checked_unwrap()
382            .error_handler
383            .debug_checked_unwrap()
384    };
385
386    let trigger: Trigger<E, B> = Trigger::new(
387        // SAFETY: Caller ensures `ptr` is castable to `&mut T`
388        unsafe { ptr.deref_mut() },
389        propagate,
390        observer_trigger,
391    );
392    // SAFETY:
393    // - observer was triggered so must have an `Observer` component.
394    // - observer cannot be dropped or mutated until after the system pointer is already dropped.
395    let system: *mut dyn ObserverSystem<E, B> = unsafe {
396        let mut observe = observer_cell.get_mut::<Observer>().debug_checked_unwrap();
397        let system = observe.system.downcast_mut::<S>().unwrap();
398        &mut *system
399    };
400
401    // SAFETY:
402    // - `update_archetype_component_access` is called first
403    // - there are no outstanding references to world except a private component
404    // - system is an `ObserverSystem` so won't mutate world beyond the access of a `DeferredWorld`
405    //   and is never exclusive
406    // - system is the same type erased system from above
407    unsafe {
408        (*system).update_archetype_component_access(world);
409        match (*system).validate_param_unsafe(world) {
410            Ok(()) => {
411                if let Err(err) = (*system).run_unsafe(trigger, world) {
412                    error_handler(
413                        err,
414                        ErrorContext::Observer {
415                            name: (*system).name(),
416                            last_run: (*system).get_last_run(),
417                        },
418                    );
419                };
420                (*system).queue_deferred(world.into_deferred());
421            }
422            Err(e) => {
423                if !e.skipped {
424                    error_handler(
425                        e.into(),
426                        ErrorContext::Observer {
427                            name: (*system).name(),
428                            last_run: (*system).get_last_run(),
429                        },
430                    );
431                }
432            }
433        }
434    }
435}
436
437/// A [`ComponentHook`] used by [`Observer`] to handle its [`on-add`](`crate::component::ComponentHooks::on_add`).
438///
439/// This function exists separate from [`Observer`] to allow [`Observer`] to have its type parameters
440/// erased.
441///
442/// The type parameters of this function _must_ match those used to create the [`Observer`].
443/// As such, it is recommended to only use this function within the [`Observer::new`] method to
444/// ensure type parameters match.
445fn hook_on_add<E: Event, B: Bundle, S: ObserverSystem<E, B>>(
446    mut world: DeferredWorld<'_>,
447    HookContext { entity, .. }: HookContext,
448) {
449    world.commands().queue(move |world: &mut World| {
450        let event_id = E::register_component_id(world);
451        let mut components = Vec::new();
452        B::component_ids(&mut world.components_registrator(), &mut |id| {
453            components.push(id);
454        });
455        let mut descriptor = ObserverDescriptor {
456            events: vec![event_id],
457            components,
458            ..Default::default()
459        };
460
461        let error_handler = default_error_handler();
462
463        // Initialize System
464        let system: *mut dyn ObserverSystem<E, B> =
465            if let Some(mut observe) = world.get_mut::<Observer>(entity) {
466                descriptor.merge(&observe.descriptor);
467                if observe.error_handler.is_none() {
468                    observe.error_handler = Some(error_handler);
469                }
470                let system = observe.system.downcast_mut::<S>().unwrap();
471                &mut *system
472            } else {
473                return;
474            };
475        // SAFETY: World reference is exclusive and initialize does not touch system, so references do not alias
476        unsafe {
477            (*system).initialize(world);
478        }
479
480        {
481            let mut entity = world.entity_mut(entity);
482            if let crate::world::Entry::Vacant(entry) = entity.entry::<ObserverState>() {
483                entry.insert(ObserverState {
484                    descriptor,
485                    runner: observer_system_runner::<E, B, S>,
486                    ..Default::default()
487                });
488            }
489        }
490    });
491}
492
493#[cfg(test)]
494mod tests {
495    use super::*;
496    use crate::{event::Event, observer::Trigger};
497
498    #[derive(Event)]
499    struct TriggerEvent;
500
501    #[test]
502    #[should_panic(expected = "I failed!")]
503    fn test_fallible_observer() {
504        fn system(_: Trigger<TriggerEvent>) -> Result {
505            Err("I failed!".into())
506        }
507
508        let mut world = World::default();
509        world.add_observer(system);
510        Schedule::default().run(&mut world);
511        world.trigger(TriggerEvent);
512    }
513
514    #[test]
515    fn test_fallible_observer_ignored_errors() {
516        #[derive(Resource, Default)]
517        struct Ran(bool);
518
519        fn system(_: Trigger<TriggerEvent>, mut ran: ResMut<Ran>) -> Result {
520            ran.0 = true;
521            Err("I failed!".into())
522        }
523
524        let mut world = World::default();
525        world.init_resource::<Ran>();
526        let observer = Observer::new(system).with_error_handler(crate::error::ignore);
527        world.spawn(observer);
528        Schedule::default().run(&mut world);
529        world.trigger(TriggerEvent);
530        assert!(world.resource::<Ran>().0);
531    }
532}