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