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