Skip to main content

bevy_ecs/observer/
distributed_storage.rs

1//! Information about observers that is stored on the entities themselves.
2//!
3//! This allows for easier cleanup, better inspection, and more flexible querying.
4//!
5//! Each observer is associated with an entity, defined by the [`Observer`] component.
6//! The [`Observer`] component contains the system that will be run when the observer is triggered,
7//! and the [`ObserverDescriptor`] which contains information about what the observer is observing.
8//!
9//! When we watch entities, we add the [`ObservedBy`] component to those entities,
10//! which links back to the observer entity.
11
12use core::any::Any;
13
14use core::marker::PhantomData;
15
16use crate::{
17    component::{ComponentCloneBehavior, ComponentId, Mutable, StorageType},
18    error::{ErrorContext, ErrorHandler},
19    event::EventKey,
20    lifecycle::{ComponentHook, HookContext},
21    observer::{
22        condition::{ObserverCondition, ObserverWithCondition, ObserverWithConditionMarker},
23        observer_system_runner, ObserverRunner,
24    },
25    prelude::*,
26    system::{IntoObserverSystem, ObserverSystem},
27    world::DeferredWorld,
28};
29use alloc::boxed::Box;
30use alloc::vec::Vec;
31use bevy_utils::prelude::DebugName;
32
33#[cfg(feature = "bevy_reflect")]
34use crate::prelude::ReflectComponent;
35
36/// An [`Observer`] system. Add this [`Component`] to an [`Entity`] to turn it into an "observer".
37///
38/// Observers watch for a "trigger" of a specific [`Event`]. An event can be triggered on the [`World`]
39/// by calling [`World::trigger`]. It can also be queued up as a [`Command`] using [`Commands::trigger`].
40///
41/// When a [`World`] triggers an [`Event`], it will immediately run every [`Observer`] that watches for that [`Event`].
42///
43/// # Usage
44///
45/// The simplest usage of the observer pattern looks like this:
46///
47/// ```
48/// # use bevy_ecs::prelude::*;
49/// # let mut world = World::default();
50/// #[derive(Event)]
51/// struct Speak {
52///     message: String,
53/// }
54///
55/// world.add_observer(|event: On<Speak>| {
56///     println!("{}", event.message);
57/// });
58///
59/// world.trigger(Speak {
60///     message: "Hello!".into(),
61/// });
62/// ```
63///
64/// Notice that we used [`World::add_observer`]. This is just a shorthand for spawning an [`Entity`] with an [`Observer`] manually:
65///
66/// ```
67/// # use bevy_ecs::prelude::*;
68/// # let mut world = World::default();
69/// # #[derive(Event)]
70/// # struct Speak;
71/// // These are functionally the same:
72/// world.add_observer(|event: On<Speak>| {});
73/// world.spawn(Observer::new(|event: On<Speak>| {}));
74/// ```
75///
76/// Observers are a specialized [`System`] called an [`ObserverSystem`]. The first parameter must be [`On`], which provides access
77/// to the [`Event`], the [`Trigger`], and some additional execution context.
78///
79/// Because they are systems, they can access arbitrary [`World`] data by adding [`SystemParam`]s:
80///
81/// ```
82/// # use bevy_ecs::prelude::*;
83/// # let mut world = World::default();
84/// # #[derive(Event)]
85/// # struct PrintNames;
86/// # #[derive(Component, Debug)]
87/// # struct Name;
88/// world.add_observer(|event: On<PrintNames>, names: Query<&Name>| {
89///     for name in &names {
90///         println!("{name:?}");
91///     }
92/// });
93/// ```
94///
95/// You can also add [`Commands`], which means you can spawn new entities, insert new components, etc:
96///
97/// ```
98/// # use bevy_ecs::prelude::*;
99/// # let mut world = World::default();
100/// # #[derive(Event)]
101/// # struct SpawnThing;
102/// # #[derive(Component, Debug)]
103/// # struct Thing;
104/// world.add_observer(|event: On<SpawnThing>, mut commands: Commands| {
105///     commands.spawn(Thing);
106/// });
107/// ```
108///
109/// Observers can also trigger new events:
110///
111/// ```
112/// # use bevy_ecs::prelude::*;
113/// # let mut world = World::default();
114/// # #[derive(Event)]
115/// # struct A;
116/// # #[derive(Event)]
117/// # struct B;
118/// world.add_observer(|event: On<A>, mut commands: Commands| {
119///     commands.trigger(B);
120/// });
121/// ```
122///
123/// When the commands are flushed (including these "nested triggers") they will be
124/// recursively evaluated until there are no commands left, meaning nested triggers all
125/// evaluate at the same time!
126///
127/// ## Event [`Trigger`] behavior
128///
129/// Each [`Event`] defines a [`Trigger`] behavior, which determines _which_ observers will run for the given [`Event`] and _how_ they will be run.
130///
131/// [`Event`] by default (when derived) uses [`GlobalTrigger`](crate::event::GlobalTrigger). When it is triggered any [`Observer`] watching for it will be run.
132///
133/// ## Event sub-types
134///
135/// There are some built-in specialized [`Event`] types with custom [`Trigger`] logic:
136///
137/// - [`EntityEvent`] / [`EntityTrigger`](crate::event::EntityTrigger): An [`Event`] that targets a _specific_ entity. This also has opt-in support for
138///   "event bubbling" behavior. See [`EntityEvent`] for details.
139/// - [`EntityComponentsTrigger`](crate::event::EntityComponentsTrigger): An [`Event`] that targets an entity _and_ one or more components on that entity.
140///   This is used for [component lifecycle events](crate::lifecycle).
141///
142/// You can also define your own!
143///
144/// ## Observer execution timing
145///
146/// Observers triggered via [`World::trigger`] are evaluated immediately, as are all commands they queue up.
147///
148/// Observers triggered via [`Commands::trigger`] are evaluated at the next sync point in the ECS schedule, just like any other [`Command`].
149///
150/// To control the relative ordering of observer trigger commands sent from different systems,
151/// order the systems in the schedule relative to each other.
152///
153/// Currently, Bevy does not provide [a way to specify the relative ordering of observers](https://github.com/bevyengine/bevy/issues/14890)
154/// watching for the same event. Their ordering is considered to be arbitrary. It is recommended to make no
155/// assumptions about their execution order.
156///
157/// Commands sent by observers are [currently not immediately applied](https://github.com/bevyengine/bevy/issues/19569).
158/// Instead, all queued observers will run, and then all of the commands from those observers will be applied.
159///
160/// ## [`ObservedBy`]
161///
162/// When entities are observed, they will receive an [`ObservedBy`] component,
163/// which will be updated to track the observers that are currently observing them.
164///
165/// ## Manual [`Observer`] target configuration
166///
167/// You can manually control the targets that an observer is watching by calling builder methods like [`Observer::with_entity`]
168/// _before_ inserting the [`Observer`] component.
169///
170/// In general, it is better to use the [`EntityWorldMut::observe`] or [`EntityCommands::observe`] methods,
171/// which spawns a new observer, and configures it to watch the entity it is called on.
172///
173/// ## Cleaning up observers
174///
175/// If an [`EntityEvent`] [`Observer`] targets specific entities, and all of those entities are despawned, the [`Observer`] entity will also be despawned.
176/// This protects against observer "garbage" building up over time.
177///
178/// ## Component lifecycle events: Observers vs Hooks
179///
180/// It is important to note that observers, just like [hooks](crate::lifecycle::ComponentHooks),
181/// can watch for and respond to [lifecycle](crate::lifecycle) events.
182/// Unlike hooks, observers are not treated as an "innate" part of component behavior:
183/// they can be added or removed at runtime, and multiple observers
184/// can be registered for the same lifecycle event for the same component.
185///
186/// The ordering of hooks versus observers differs based on the lifecycle event in question:
187///
188/// - when adding components, hooks are evaluated first, then observers
189/// - when removing components, observers are evaluated first, then hooks
190///
191/// This allows hooks to act as constructors and destructors for components,
192/// as they always have the first and final say in the component's lifecycle.
193///
194/// ## Observer re-targeting
195///
196/// Currently, [observers cannot be retargeted after spawning](https://github.com/bevyengine/bevy/issues/19587):
197/// despawn and respawn an observer as a workaround.
198///
199/// ## Internal observer cache
200///
201/// For more efficient observer triggering, Observers make use of the internal [`CachedObservers`](crate::observer::CachedObservers) storage.
202/// In general, this is an implementation detail developers don't need to worry about, but it can be used when implementing custom [`Trigger`](crate::event::Trigger)
203/// types, or to add "dynamic" observers for cases like scripting / modding.
204///
205/// [`SystemParam`]: crate::system::SystemParam
206/// [`Trigger`]: crate::event::Trigger
207pub struct Observer {
208    hook_on_add: ComponentHook,
209    pub(crate) error_handler: Option<ErrorHandler>,
210    pub(crate) system: Box<dyn AnyNamedSystem>,
211    pub(crate) descriptor: ObserverDescriptor,
212    pub(crate) last_trigger_id: u32,
213    pub(crate) despawned_watched_entities: u32,
214    pub(crate) runner: ObserverRunner,
215    pub(crate) conditions: Vec<ObserverCondition>,
216}
217
218impl Observer {
219    /// Creates a new [`Observer`], which defaults to a "global" observer. This means it will run _whenever_ an event of type `E` is triggered.
220    ///
221    /// # Panics
222    ///
223    /// Panics if the given system is an exclusive system.
224    pub fn new<E: Event, B: Bundle, M, I: IntoObserverSystem<E, B, M>>(system: I) -> Self {
225        let system = Box::new(IntoObserverSystem::into_system(system));
226        assert!(
227            !system.is_exclusive(),
228            concat!(
229                "Exclusive system `{}` may not be used as observer.\n",
230                "Instead of `&mut World`, use either `DeferredWorld` if you do not need structural changes, or `Commands` if you do."
231            ),
232            system.name()
233        );
234        Self {
235            system,
236            descriptor: Default::default(),
237            hook_on_add: hook_on_add::<E, B, I::System>,
238            error_handler: None,
239            runner: observer_system_runner::<E, B, I::System>,
240            despawned_watched_entities: 0,
241            last_trigger_id: 0,
242            conditions: Vec::new(),
243        }
244    }
245
246    /// Creates a new [`Observer`] with custom runner, this is mostly used for dynamic event observers
247    pub fn with_dynamic_runner(runner: ObserverRunner) -> Self {
248        Self {
249            system: Box::new(IntoSystem::into_system(|| {})),
250            descriptor: Default::default(),
251            hook_on_add: |mut world, hook_context| {
252                let default_error_handler = world.fallback_error_handler();
253                world.commands().queue(move |world: &mut World| {
254                    let entity = hook_context.entity;
255                    let mut conditions = {
256                        let Some(mut observe) = world.get_mut::<Observer>(entity) else {
257                            return;
258                        };
259                        if observe.descriptor.event_keys.is_empty() {
260                            return;
261                        }
262                        if observe.error_handler.is_none() {
263                            observe.error_handler = Some(default_error_handler);
264                        }
265                        core::mem::take(&mut observe.conditions)
266                    };
267                    for condition in &mut conditions {
268                        condition.initialize(world);
269                    }
270                    if let Some(mut observe) = world.get_mut::<Observer>(entity) {
271                        observe.conditions = conditions;
272                    }
273                    world.register_observer(entity);
274                });
275            },
276            error_handler: None,
277            runner,
278            despawned_watched_entities: 0,
279            last_trigger_id: 0,
280            conditions: Vec::new(),
281        }
282    }
283
284    /// Observes the given `entity` (in addition to any entity already being observed).
285    /// This will cause the [`Observer`] to run whenever an [`EntityEvent::event_target`] is the given `entity`.
286    /// Note that if this is called _after_ an [`Observer`] is spawned, it will produce no effects.
287    pub fn with_entity(mut self, entity: Entity) -> Self {
288        self.watch_entity(entity);
289        self
290    }
291
292    /// Observes the given `entities` (in addition to any entity already being observed).
293    /// This will cause the [`Observer`] to run whenever an [`EntityEvent::event_target`] is any of the `entities`.
294    /// Note that if this is called _after_ an [`Observer`] is spawned, it will produce no effects.
295    pub fn with_entities<I: IntoIterator<Item = Entity>>(mut self, entities: I) -> Self {
296        self.watch_entities(entities);
297        self
298    }
299
300    /// Observes the given `entity` (in addition to any entity already being observed).
301    /// This will cause the [`Observer`] to run whenever an [`EntityEvent::event_target`] is the given `entity`.
302    /// Note that if this is called _after_ an [`Observer`] is spawned, it will produce no effects.
303    pub fn watch_entity(&mut self, entity: Entity) {
304        self.descriptor.entities.push(entity);
305    }
306
307    /// Observes the given `entity` (in addition to any entity already being observed).
308    /// This will cause the [`Observer`] to run whenever an [`EntityEvent::event_target`] is any of the `entities`.
309    /// Note that if this is called _after_ an [`Observer`] is spawned, it will produce no effects.
310    pub fn watch_entities<I: IntoIterator<Item = Entity>>(&mut self, entities: I) {
311        self.descriptor.entities.extend(entities);
312    }
313
314    /// Observes the given `component`. This will cause the [`Observer`] to run whenever the [`Event`] has
315    /// an [`EntityComponentsTrigger`](crate::event::EntityComponentsTrigger) that targets the given `component`.
316    pub fn with_component(mut self, component: ComponentId) -> Self {
317        self.descriptor.components.push(component);
318        self
319    }
320
321    /// Observes the given `components`. This will cause the [`Observer`] to run whenever the [`Event`] has
322    /// an [`EntityComponentsTrigger`](crate::event::EntityComponentsTrigger) that targets any of the `components`.
323    pub fn with_components<I: IntoIterator<Item = ComponentId>>(mut self, components: I) -> Self {
324        self.descriptor.components.extend(components);
325        self
326    }
327
328    /// Observes the given `event_key`. This will cause the [`Observer`] to run whenever an event with the given [`EventKey`]
329    /// is triggered.
330    /// # Safety
331    /// The type of the `event_key` [`EventKey`] _must_ match the actual value
332    /// of the event passed into the observer system.
333    pub unsafe fn with_event_key(mut self, event_key: EventKey) -> Self {
334        self.descriptor.event_keys.push(event_key);
335        self
336    }
337
338    /// Sets the error handler to use for this observer.
339    ///
340    /// See the [`error` module-level documentation](crate::error) for more information.
341    pub fn with_error_handler(mut self, error_handler: fn(BevyError, ErrorContext)) -> Self {
342        self.error_handler = Some(error_handler);
343        self
344    }
345
346    /// Adds a run condition to this observer.
347    ///
348    /// The observer will only run if all conditions return `true` (AND semantics).
349    /// Multiple conditions can be added by chaining `run_if` calls.
350    pub fn run_if<M>(mut self, condition: impl SystemCondition<M>) -> Self {
351        self.conditions.push(ObserverCondition::new(condition));
352        self
353    }
354
355    /// Returns the [`ObserverDescriptor`] for this [`Observer`].
356    pub fn descriptor(&self) -> &ObserverDescriptor {
357        &self.descriptor
358    }
359
360    /// Returns the name of the [`Observer`]'s system .
361    pub fn system_name(&self) -> DebugName {
362        self.system.system_name()
363    }
364}
365
366impl Component for Observer {
367    const STORAGE_TYPE: StorageType = StorageType::SparseSet;
368    type Mutability = Mutable;
369    fn on_add() -> Option<ComponentHook> {
370        Some(|world, context| {
371            let Some(observe) = world.get::<Self>(context.entity) else {
372                return;
373            };
374            let hook = observe.hook_on_add;
375            hook(world, context);
376        })
377    }
378    fn on_remove() -> Option<ComponentHook> {
379        Some(|mut world, HookContext { entity, .. }| {
380            let descriptor = core::mem::take(
381                &mut world
382                    .entity_mut(entity)
383                    .get_mut::<Self>()
384                    .unwrap()
385                    .as_mut()
386                    .descriptor,
387            );
388            world.commands().queue(move |world: &mut World| {
389                world.unregister_observer(entity, descriptor);
390            });
391        })
392    }
393}
394
395/// Store information about what an [`Observer`] observes.
396///
397/// This information is stored inside of the [`Observer`] component,
398#[derive(Default, Clone)]
399pub struct ObserverDescriptor {
400    /// The event keys the observer is watching.
401    pub(super) event_keys: Vec<EventKey>,
402
403    /// The components the observer is watching.
404    pub(super) components: Vec<ComponentId>,
405
406    /// The entities the observer is watching.
407    pub(super) entities: Vec<Entity>,
408}
409
410impl ObserverDescriptor {
411    /// Add the given `event_keys` to the descriptor.
412    /// # Safety
413    /// The type of each [`EventKey`] in `event_keys` _must_ match the actual value
414    /// of the event passed into the observer.
415    pub unsafe fn with_event_keys(mut self, event_keys: Vec<EventKey>) -> Self {
416        self.event_keys = event_keys;
417        self
418    }
419
420    /// Add the given `components` to the descriptor.
421    pub fn with_components(mut self, components: Vec<ComponentId>) -> Self {
422        self.components = components;
423        self
424    }
425
426    /// Add the given `entities` to the descriptor.
427    pub fn with_entities(mut self, entities: Vec<Entity>) -> Self {
428        self.entities = entities;
429        self
430    }
431
432    /// Returns the `event_keys` that the observer is watching.
433    pub fn event_keys(&self) -> &[EventKey] {
434        &self.event_keys
435    }
436
437    /// Returns the `components` that the observer is watching.
438    pub fn components(&self) -> &[ComponentId] {
439        &self.components
440    }
441
442    /// Returns the `entities` that the observer is watching.
443    pub fn entities(&self) -> &[Entity] {
444        &self.entities
445    }
446}
447
448/// A [`ComponentHook`] used by [`Observer`] to handle its [`on-add`](`crate::lifecycle::ComponentHooks::on_add`).
449///
450/// This function exists separate from [`Observer`] to allow [`Observer`] to have its type parameters
451/// erased.
452///
453/// The type parameters of this function _must_ match those used to create the [`Observer`].
454/// As such, it is recommended to only use this function within the [`Observer::new`] method to
455/// ensure type parameters match.
456fn hook_on_add<E: Event, B: Bundle, S: ObserverSystem<E, B>>(
457    mut world: DeferredWorld<'_>,
458    HookContext { entity, .. }: HookContext,
459) {
460    world.commands().queue(move |world: &mut World| {
461        let event_key = world.register_event_key::<E>();
462        let components = B::component_ids(&mut world.components_registrator());
463
464        let system_ptr: *mut dyn ObserverSystem<E, B> = {
465            let Some(mut observer) = world.get_mut::<Observer>(entity) else {
466                return;
467            };
468            observer.descriptor.event_keys.push(event_key);
469            observer.descriptor.components.extend(components);
470
471            let system: &mut dyn Any = observer.system.as_mut();
472            core::ptr::from_mut(system.downcast_mut::<S>().unwrap())
473        };
474
475        // SAFETY: World reference is exclusive and initialize does not touch system, so references do not alias
476        unsafe {
477            (*system_ptr).initialize(world);
478        }
479
480        let mut conditions = {
481            let Some(mut observer) = world.get_mut::<Observer>(entity) else {
482                return;
483            };
484            core::mem::take(&mut observer.conditions)
485        };
486
487        for condition in &mut conditions {
488            condition.initialize(world);
489        }
490
491        if let Some(mut observer) = world.get_mut::<Observer>(entity) {
492            observer.conditions = conditions;
493        }
494
495        world.register_observer(entity);
496    });
497}
498
499/// Tracks a list of entity observers for the [`Entity`] [`ObservedBy`] is added to.
500#[derive(Default, Debug)]
501#[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))]
502#[cfg_attr(feature = "bevy_reflect", reflect(Component, Debug))]
503pub struct ObservedBy(pub(crate) Vec<Entity>);
504
505impl ObservedBy {
506    /// Provides a read-only reference to the list of entities observing this entity.
507    pub fn get(&self) -> &[Entity] {
508        &self.0
509    }
510}
511
512impl Component for ObservedBy {
513    const STORAGE_TYPE: StorageType = StorageType::SparseSet;
514    type Mutability = Mutable;
515
516    fn on_remove() -> Option<ComponentHook> {
517        Some(|mut world, HookContext { entity, .. }| {
518            let observed_by = {
519                let mut component = world.get_mut::<ObservedBy>(entity).unwrap();
520                core::mem::take(&mut component.0)
521            };
522            for e in observed_by {
523                let (total_entities, despawned_watched_entities) = {
524                    let Ok(mut entity_mut) = world.get_entity_mut(e) else {
525                        continue;
526                    };
527                    let Some(mut state) = entity_mut.get_mut::<Observer>() else {
528                        continue;
529                    };
530                    state.despawned_watched_entities += 1;
531                    (
532                        state.descriptor.entities.len(),
533                        state.despawned_watched_entities as usize,
534                    )
535                };
536
537                // Despawn Observer if it has no more active sources.
538                if total_entities == despawned_watched_entities {
539                    world.commands().entity(e).despawn();
540                }
541            }
542        })
543    }
544
545    fn clone_behavior() -> ComponentCloneBehavior {
546        ComponentCloneBehavior::Ignore
547    }
548}
549
550pub(crate) trait AnyNamedSystem: Any + Send + Sync + 'static {
551    fn system_name(&self) -> DebugName;
552}
553
554impl<T: Any + System> AnyNamedSystem for T {
555    fn system_name(&self) -> DebugName {
556        self.name()
557    }
558}
559
560/// Trait for types that can be converted into an [`Observer`].
561pub trait IntoObserver<Marker>: Send + 'static {
562    /// Converts this type into an [`Observer`].
563    fn into_observer(self) -> Observer;
564}
565
566impl IntoObserver<()> for Observer {
567    fn into_observer(self) -> Observer {
568        self
569    }
570}
571
572impl<E: Event, B: Bundle, M, T: IntoObserverSystem<E, B, M>> IntoObserver<(E, B, M)> for T {
573    fn into_observer(self) -> Observer {
574        Observer::new(self)
575    }
576}
577
578impl<E: Event, B: Bundle, M: 'static, S: IntoObserverSystem<E, B, M>>
579    IntoObserver<ObserverWithConditionMarker> for ObserverWithCondition<E, B, M, S>
580{
581    fn into_observer(self) -> Observer {
582        let (system, conditions) = self.take_conditions();
583        let mut observer = Observer::new(system);
584        observer.conditions = conditions;
585        observer
586    }
587}
588
589/// Trait for types that can be converted into an entity-targeting [`Observer`].
590///
591/// This trait enforces that the event type implements [`EntityEvent`].
592#[diagnostic::on_unimplemented(
593    message = "`{Self}` cannot be used as an entity observer",
594    note = "entity observers require the event type to implement `EntityEvent`"
595)]
596pub trait IntoEntityObserver<Marker>: Send + 'static {
597    /// Converts this type into an [`Observer`] that watches the given entity.
598    fn into_observer_for_entity(self, entity: Entity) -> Observer;
599}
600
601impl<E: EntityEvent, B: Bundle, M, T: IntoObserverSystem<E, B, M>> IntoEntityObserver<(E, B, M)>
602    for T
603{
604    fn into_observer_for_entity(self, entity: Entity) -> Observer {
605        Observer::new(self).with_entity(entity)
606    }
607}
608
609impl<E: EntityEvent, B: Bundle, M: 'static, S: IntoObserverSystem<E, B, M>>
610    IntoEntityObserver<ObserverWithConditionMarker> for ObserverWithCondition<E, B, M, S>
611{
612    fn into_observer_for_entity(self, entity: Entity) -> Observer {
613        let (system, conditions) = self.take_conditions();
614        let mut observer = Observer::new(system);
615        observer.conditions = conditions;
616        observer.with_entity(entity)
617    }
618}
619
620/// Extension trait for adding run conditions to observer systems.
621pub trait ObserverSystemExt<E: Event, B: Bundle, M>: IntoObserverSystem<E, B, M> + Sized {
622    /// Adds a run condition to this observer system.
623    ///
624    /// The observer will only run if the condition returns `true`.
625    /// Multiple conditions can be chained (AND semantics).
626    fn run_if<C, CM>(self, condition: C) -> ObserverWithCondition<E, B, M, Self>
627    where
628        C: SystemCondition<CM>,
629    {
630        ObserverWithCondition {
631            system: self,
632            conditions: alloc::vec![Box::new(IntoSystem::into_system(condition))],
633            _marker: PhantomData,
634        }
635    }
636}
637
638impl<E: Event, B: Bundle, M, T: IntoObserverSystem<E, B, M>> ObserverSystemExt<E, B, M> for T {}