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