bevy_ecs/observer/
runner.rs

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