Struct Observer
pub struct Observer { /* private fields */ }Expand description
An Observer system. Add this Component to an Entity to turn it into an “observer”.
Observers watch for a “trigger” of a specific Event. An event can be triggered on the World
by calling World::trigger. It can also be queued up as a [Command] using Commands::trigger.
When a World triggers an Event, it will immediately run every Observer that watches for that Event.
§Usage
The simplest usage of the observer pattern looks like this:
#[derive(Event)]
struct Speak {
message: String,
}
world.add_observer(|event: On<Speak>| {
println!("{}", event.message);
});
world.trigger(Speak {
message: "Hello!".into(),
});Notice that we used World::add_observer. This is just a shorthand for spawning an Entity with an Observer manually:
// These are functionally the same:
world.add_observer(|event: On<Speak>| {});
world.spawn(Observer::new(|event: On<Speak>| {}));Observers are a specialized System called an [ObserverSystem]. The first parameter must be On, which provides access
to the Event, the Trigger, and some additional execution context.
Because they are systems, they can access arbitrary World data by adding SystemParams:
world.add_observer(|event: On<PrintNames>, names: Query<&Name>| {
for name in &names {
println!("{name:?}");
}
});You can also add Commands, which means you can spawn new entities, insert new components, etc:
world.add_observer(|event: On<SpawnThing>, mut commands: Commands| {
commands.spawn(Thing);
});Observers can also trigger new events:
world.add_observer(|event: On<A>, mut commands: Commands| {
commands.trigger(B);
});When the commands are flushed (including these “nested triggers”) they will be recursively evaluated until there are no commands left, meaning nested triggers all evaluate at the same time!
§Event Trigger behavior
Each Event defines a Trigger behavior, which determines which observers will run for the given Event and how they will be run.
Event by default (when derived) uses GlobalTrigger. When it is triggered any Observer watching for it will be run.
§Event sub-types
There are some built-in specialized Event types with custom Trigger logic:
EntityEvent/EntityTrigger: AnEventthat targets a specific entity. This also has opt-in support for “event bubbling” behavior. SeeEntityEventfor details.EntityComponentsTrigger: AnEventthat targets an entity and one or more components on that entity. This is used for component lifecycle events.
You can also define your own!
§Observer execution timing
Observers triggered via World::trigger are evaluated immediately, as are all commands they queue up.
Observers triggered via Commands::trigger are evaluated at the next sync point in the ECS schedule, just like any other [Command].
To control the relative ordering of observer trigger commands sent from different systems, order the systems in the schedule relative to each other.
Currently, Bevy does not provide a way to specify the relative ordering of observers watching for the same event. Their ordering is considered to be arbitrary. It is recommended to make no assumptions about their execution order.
Commands sent by observers are currently not immediately applied. Instead, all queued observers will run, and then all of the commands from those observers will be applied.
§[ObservedBy]
When entities are observed, they will receive an [ObservedBy] component,
which will be updated to track the observers that are currently observing them.
§Manual Observer target configuration
You can manually control the targets that an observer is watching by calling builder methods like Observer::with_entity
before inserting the Observer component.
In general, it is better to use the EntityWorldMut::observe or EntityCommands::observe methods,
which spawns a new observer, and configures it to watch the entity it is called on.
§Cleaning up observers
If an EntityEvent Observer targets specific entities, and all of those entities are despawned, the Observer entity will also be despawned.
This protects against observer “garbage” building up over time.
§Component lifecycle events: Observers vs Hooks
It is important to note that observers, just like hooks, can watch for and respond to lifecycle events. Unlike hooks, observers are not treated as an “innate” part of component behavior: they can be added or removed at runtime, and multiple observers can be registered for the same lifecycle event for the same component.
The ordering of hooks versus observers differs based on the lifecycle event in question:
- when adding components, hooks are evaluated first, then observers
- when removing components, observers are evaluated first, then hooks
This allows hooks to act as constructors and destructors for components, as they always have the first and final say in the component’s lifecycle.
§Observer re-targeting
Currently, observers cannot be retargeted after spawning: despawn and respawn an observer as a workaround.
§Internal observer cache
For more efficient observer triggering, Observers make use of the internal CachedObservers storage.
In general, this is an implementation detail developers don’t need to worry about, but it can be used when implementing custom Trigger
types, or to add “dynamic” observers for cases like scripting / modding.
Implementations§
§impl Observer
impl Observer
pub fn with_dynamic_runner(
runner: unsafe fn(DeferredWorld<'_>, Entity, &TriggerContext, PtrMut<'_>, PtrMut<'_>),
) -> Observer
pub fn with_dynamic_runner( runner: unsafe fn(DeferredWorld<'_>, Entity, &TriggerContext, PtrMut<'_>, PtrMut<'_>), ) -> Observer
Creates a new Observer with custom runner, this is mostly used for dynamic event observers
pub fn with_entity(self, entity: Entity) -> Observer
pub fn with_entity(self, entity: Entity) -> Observer
Observes the given entity (in addition to any entity already being observed).
This will cause the Observer to run whenever an EntityEvent::event_target is the given entity.
Note that if this is called after an Observer is spawned, it will produce no effects.
pub fn with_entities<I>(self, entities: I) -> Observerwhere
I: IntoIterator<Item = Entity>,
pub fn with_entities<I>(self, entities: I) -> Observerwhere
I: IntoIterator<Item = Entity>,
Observes the given entities (in addition to any entity already being observed).
This will cause the Observer to run whenever an EntityEvent::event_target is any of the entities.
Note that if this is called after an Observer is spawned, it will produce no effects.
pub fn watch_entity(&mut self, entity: Entity)
pub fn watch_entity(&mut self, entity: Entity)
Observes the given entity (in addition to any entity already being observed).
This will cause the Observer to run whenever an EntityEvent::event_target is the given entity.
Note that if this is called after an Observer is spawned, it will produce no effects.
pub fn watch_entities<I>(&mut self, entities: I)where
I: IntoIterator<Item = Entity>,
pub fn watch_entities<I>(&mut self, entities: I)where
I: IntoIterator<Item = Entity>,
Observes the given entity (in addition to any entity already being observed).
This will cause the Observer to run whenever an EntityEvent::event_target is any of the entities.
Note that if this is called after an Observer is spawned, it will produce no effects.
pub fn with_component(self, component: ComponentId) -> Observer
pub fn with_component(self, component: ComponentId) -> Observer
Observes the given component. This will cause the Observer to run whenever the Event has
an EntityComponentsTrigger that targets the given component.
pub fn with_components<I>(self, components: I) -> Observerwhere
I: IntoIterator<Item = ComponentId>,
pub fn with_components<I>(self, components: I) -> Observerwhere
I: IntoIterator<Item = ComponentId>,
Observes the given components. This will cause the Observer to run whenever the Event has
an EntityComponentsTrigger that targets any of the components.
pub unsafe fn with_event_key(self, event_key: EventKey) -> Observer
pub unsafe fn with_event_key(self, event_key: EventKey) -> Observer
pub fn with_error_handler(
self,
error_handler: fn(BevyError, ErrorContext),
) -> Observer
pub fn with_error_handler( self, error_handler: fn(BevyError, ErrorContext), ) -> Observer
Sets the error handler to use for this observer.
See the error module-level documentation for more information.
pub fn run_if<M>(self, condition: impl SystemCondition<M>) -> Observer
pub fn run_if<M>(self, condition: impl SystemCondition<M>) -> Observer
Adds a run condition to this observer.
The observer will only run if all conditions return true (AND semantics).
Multiple conditions can be added by chaining run_if calls.
pub fn descriptor(&self) -> &ObserverDescriptor
pub fn descriptor(&self) -> &ObserverDescriptor
Returns the [ObserverDescriptor] for this Observer.
pub fn system_name(&self) -> DebugName
pub fn system_name(&self) -> DebugName
Returns the name of the Observer’s system .
Trait Implementations§
§impl Component for Observer
impl Component for Observer
§const STORAGE_TYPE: StorageType = StorageType::SparseSet
const STORAGE_TYPE: StorageType = StorageType::SparseSet
§type Mutability = Mutable
type Mutability = Mutable
Component<Mutability = Mutable>,
while immutable components will instead have Component<Mutability = Immutable>. Read more§fn on_discard() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_discard() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
§fn on_despawn() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
fn on_despawn() -> Option<for<'w> fn(DeferredWorld<'w>, HookContext)>
§fn register_required_components(
_component_id: ComponentId,
_required_components: &mut RequiredComponentsRegistrator<'_, '_>,
)
fn register_required_components( _component_id: ComponentId, _required_components: &mut RequiredComponentsRegistrator<'_, '_>, )
§fn clone_behavior() -> ComponentCloneBehavior
fn clone_behavior() -> ComponentCloneBehavior
§fn map_entities<E>(_this: &mut Self, _mapper: &mut E)where
E: EntityMapper,
fn map_entities<E>(_this: &mut Self, _mapper: &mut E)where
E: EntityMapper,
EntityMapper. This is used to remap entities in contexts like scenes and entity cloning.
When deriving Component, this is populated by annotating fields containing entities with #[entities] Read more§fn relationship_accessor() -> Option<ComponentRelationshipAccessor<Self>>
fn relationship_accessor() -> Option<ComponentRelationshipAccessor<Self>>
ComponentRelationshipAccessor] required for working with relationships in dynamic contexts. Read more