pub struct Observer<T, B>where
T: 'static,
B: Bundle,{ /* private fields */ }
Expand description
An Observer
system. Add this Component
to an Entity
to turn it into an “observer”.
Observers listen for a “trigger” of a specific Event
. Events are triggered by calling World::trigger
or World::trigger_targets
.
Note that “buffered” events sent using EventReader
and EventWriter
are not automatically triggered. They must be triggered at a specific
point in the schedule.
§Usage
The simplest usage of the observer pattern looks like this:
#[derive(Event)]
struct Speak {
message: String,
}
world.observe(|trigger: Trigger<Speak>| {
println!("{}", trigger.event().message);
});
// Observers currently require a flush() to be registered. In the context of schedules,
// this will generally be done for you.
world.flush();
world.trigger(Speak {
message: "Hello!".into(),
});
Notice that we used World::observe
. This is just a shorthand for spawning an Observer
manually:
// These are functionally the same:
world.observe(|trigger: Trigger<Speak>| {});
world.spawn(Observer::new(|trigger: Trigger<Speak>| {}));
Observers are systems. They can access arbitrary World
data by adding SystemParam
s:
world.observe(|trigger: Trigger<PrintNames>, names: Query<&Name>| {
for name in &names {
println!("{name:?}");
}
});
Note that Trigger
must always be the first parameter.
You can also add Commands
, which means you can spawn new entities, insert new components, etc:
world.observe(|trigger: Trigger<SpawnThing>, mut commands: Commands| {
commands.spawn(Thing);
});
Observers can also trigger new events:
world.observe(|trigger: Trigger<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!
Events can be triggered for entities, which will be passed to the Observer
:
#[derive(Event)]
struct Explode;
world.observe(|trigger: Trigger<Explode>, mut commands: Commands| {
println!("Entity {:?} goes BOOM!", trigger.entity());
commands.entity(trigger.entity()).despawn();
});
world.flush();
world.trigger_targets(Explode, entity);
You can trigger multiple entities at once:
world.trigger_targets(Explode, [e1, e2]);
Observers can also watch specific entities, which enables you to assign entity-specific logic:
world.entity_mut(e1).observe(|trigger: Trigger<Explode>, mut commands: Commands| {
println!("Boom!");
commands.entity(trigger.entity()).despawn();
});
world.entity_mut(e2).observe(|trigger: Trigger<Explode>, mut commands: Commands| {
println!("The explosion fizzles! This entity is immune!");
});
If all entities watched by a given Observer
are despawned, the Observer
entity will also be despawned.
This protects against observer “garbage” building up over time.
The examples above calling EntityWorldMut::observe
to add entity-specific observer logic are (once again)
just shorthand for spawning an Observer
directly:
let mut observer = Observer::new(|trigger: Trigger<Explode>| {});
observer.watch_entity(entity);
world.spawn(observer);
Note that the Observer
component is not added to the entity it is observing. Observers should always be their own entities!
You can call Observer::watch_entity
more than once, which allows you to watch multiple entities with the same Observer
.
When first added, Observer
will also create an ObserverState
component, which registers the observer with the World
and
serves as the “source of truth” of the observer.
Implementations§
§impl<E, B> Observer<E, B>
impl<E, B> Observer<E, B>
pub fn new<M>(system: impl IntoObserverSystem<E, B, M>) -> Observer<E, B>
pub fn new<M>(system: impl IntoObserverSystem<E, B, M>) -> Observer<E, B>
Creates a new Observer
, which defaults to a “global” observer. This means it will run whenever the event E
is triggered
for any entity (or no entity).
pub fn with_entity(self, entity: Entity) -> Observer<E, B>
pub fn with_entity(self, entity: Entity) -> Observer<E, B>
pub fn watch_entity(&mut self, entity: Entity)
pub fn watch_entity(&mut self, entity: Entity)
pub fn with_component(self, component: ComponentId) -> Observer<E, B>
pub fn with_component(self, component: ComponentId) -> Observer<E, B>
pub unsafe fn with_event(self, event: ComponentId) -> Observer<E, B>
pub unsafe fn with_event(self, event: ComponentId) -> Observer<E, B>
Observe the given event
. This will cause the Observer
to run whenever an event with the given ComponentId
is triggered.
§Safety
The type of the event
ComponentId
must match the actual value
of the event passed into the observer system.
Trait Implementations§
§impl<E, B> Component for Observer<E, B>
impl<E, B> Component for Observer<E, B>
§const STORAGE_TYPE: StorageType = StorageType::SparseSet
const STORAGE_TYPE: StorageType = StorageType::SparseSet
§fn register_component_hooks(hooks: &mut ComponentHooks)
fn register_component_hooks(hooks: &mut ComponentHooks)
ComponentHooks
.Auto Trait Implementations§
impl<T, B> Freeze for Observer<T, B>
impl<T, B> !RefUnwindSafe for Observer<T, B>
impl<T, B> Send for Observer<T, B>
impl<T, B> Sync for Observer<T, B>
impl<T, B> Unpin for Observer<T, B>
impl<T, B> !UnwindSafe for Observer<T, B>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<C> Bundle for Cwhere
C: Component,
impl<C> Bundle for Cwhere
C: Component,
fn component_ids( components: &mut Components, storages: &mut Storages, ids: &mut impl FnMut(ComponentId), )
unsafe fn from_components<T, F>(ctx: &mut T, func: &mut F) -> C
§fn get_component_ids(
components: &Components,
ids: &mut impl FnMut(Option<ComponentId>),
)
fn get_component_ids( components: &Components, ids: &mut impl FnMut(Option<ComponentId>), )
§impl<T> Conv for T
impl<T> Conv for T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<C> DynamicBundle for Cwhere
C: Component,
impl<C> DynamicBundle for Cwhere
C: Component,
fn get_components(self, func: &mut impl FnMut(StorageType, OwningPtr<'_>))
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.