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}