Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/observer/distributed_storage.rs
6604 views
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
12
use core::any::Any;
13
14
use crate::{
15
component::{
16
ComponentCloneBehavior, ComponentId, Mutable, RequiredComponentsRegistrator, StorageType,
17
},
18
entity::Entity,
19
entity_disabling::Internal,
20
error::{ErrorContext, ErrorHandler},
21
event::Event,
22
lifecycle::{ComponentHook, HookContext},
23
observer::{observer_system_runner, ObserverRunner},
24
prelude::*,
25
system::{IntoObserverSystem, ObserverSystem},
26
world::DeferredWorld,
27
};
28
use alloc::boxed::Box;
29
use alloc::vec::Vec;
30
use bevy_utils::prelude::DebugName;
31
32
#[cfg(feature = "bevy_reflect")]
33
use 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
206
pub 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
216
impl 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
336
impl 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)]
376
pub 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
387
impl 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.
433
fn 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))]
462
pub struct ObservedBy(pub(crate) Vec<Entity>);
463
464
impl 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
471
impl 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
509
pub(crate) trait AnyNamedSystem: Any + Send + Sync + 'static {
510
fn system_name(&self) -> DebugName;
511
}
512
513
impl<T: Any + System> AnyNamedSystem for T {
514
fn system_name(&self) -> DebugName {
515
self.name()
516
}
517
}
518
519