pub struct ReactCommands<'w, 's> { /* private fields */ }
Expand description
Drives reactivity.
Requires ReactPlugin
.
Note that each time you register a reactor, it is assigned a unique system state (including unique Local
s). To avoid
leaking memory, be sure to revoke reactors when you are done with them. Despawn reactors are automatically cleaned up.
§Ordering and determinism
ReactCommands
requires exclusive access to an internal cache, which means the order of react events is fully
specified. Reactors of the same type will react to an event in the order they are added, and react commands will
be applied in the order they were invoked (note that all reactor registration is deferred).
Reactions to a reactor will always be resolved immediately after the reactor ends,
in the order they were queued (and so on up the reaction tree). A reactor’s component removals and entity despawns
are queued alongside child reactions, which means a removal/despawn can only be ‘seen’ once its place in the queue
has been processed. Reactors always schedule reactions to available removals/despawns after they run, so if you have
[despawn A, reaction X, despawn B], and both despawns have reactions, then despawn A will be the first despawn reacted
to at the end of reaction X (or at end of the first leaf node of a reaction branch stemming from X), before any of X’s
despawns.
A reaction tree is single-threaded by default (it may be multi-threaded if you manually invoke a bevy schedule within
the tree), so trees are deterministic. However, root-level reactive systems (systems that cause reactions but are
not themselves reactors) are subject to the ordering constraints of their callers (e.g. a bevy app schedule), and
reaction trees can only be initiated by calling apply_deferred()
. This means the order that root-level reactors are
queued, and the order of root-level removals/despawns, is unspecified by the react framework.
§Notes
A reaction tree is like a multi-layered accordion of command queues that automatically expands and resolves itself. Of note, the ‘current’ structure of that accordion tree cannot be modified. For example, you cannot add a data event reactor after an instance of a data event of that type that is below you in the reaction tree and expect the new reactor will respond to that data event instance. Moreover, already-queued reactions/ react commands cannot be removed from the tree. However, modifications to the ECS world will be reflected in the behavior of future reactors, which may effect the structure of not-yet-expanded parts of the accordion.
Component removal and entity despawn reactions can only occur if you explicitly call react_to_removals()
,
react_to_despawns()
, or react_to_all_removals_and_despawns()
. We call those automatically in reaction trees, but
if a root-level reactive system doesn’t cause any reactions then removals/despawns won’t be handled. For that reason,
we recommand always pessimistically checking for removals/despawns manually after a call to apply_deferred
after
root-level reactive systems.
WARNING: All ordering constraints may be thrown out the window with bevy native command batching.
Implementations§
Source§impl<'w, 's> ReactCommands<'w, 's>
impl<'w, 's> ReactCommands<'w, 's>
Sourcepub fn insert<C: ReactComponent>(&mut self, entity: Entity, component: C)
pub fn insert<C: ReactComponent>(&mut self, entity: Entity, component: C)
Insert a ReactComponent
to the specified entity. It can be queried with React<C>
.
- Reactions are enacted after
apply_deferred
is invoked. - Does nothing if the entity does not exist.
Sourcepub fn send<E: Send + Sync + 'static>(&mut self, event: E)
pub fn send<E: Send + Sync + 'static>(&mut self, event: E)
Send an event.
- The event is sent and reactions are enacted after
apply_deferred
is invoked. - Reactors can access the event with the bevy [
ReactEvent<E>
] system parameter.
Sourcepub fn trigger_resource_mutation<R: ReactResource + Send + Sync + 'static>(
&mut self,
)
pub fn trigger_resource_mutation<R: ReactResource + Send + Sync + 'static>( &mut self, )
Trigger resource mutation reactions.
Useful for initializing state after a reactor is registered.
Sourcepub fn revoke(&mut self, token: RevokeToken)
pub fn revoke(&mut self, token: RevokeToken)
Revoke a reactor.
- Entity reactors: revoked after
apply_deferred
is invoked. - Component, despawn, resource, event reactors: revoked immediately.
Sourcepub fn on<I, Marker>(
&mut self,
triggers: impl ReactionTriggerBundle<I>,
reactor: impl IntoSystem<I, (), Marker> + Send + Sync + 'static,
) -> RevokeToken
pub fn on<I, Marker>( &mut self, triggers: impl ReactionTriggerBundle<I>, reactor: impl IntoSystem<I, (), Marker> + Send + Sync + 'static, ) -> RevokeToken
Register a reactor triggered by ECS changes.
You can tie a reactor to multiple reaction triggers. Note that the
entity-agnostic component triggers can only be bundled with each other: insertion()
, mutation()
,
removal()
.
Duplicate triggers will be ignored.
Reactions are not merged together. If you register a reactor for triggers
(resource_mutation::<A>(), resource_mutation::<B>())
, then mutate A
and B
in succession, the reactor will
execute twice.
Example:
rcommands.on((resource_mutation::<MyRes>(), component_mutation::<MyComponent>()), my_reactor_system);
Sourcepub fn on_despawn<Marker>(
&mut self,
entity: Entity,
reactor: impl IntoSystem<(), (), Marker> + Send + Sync + 'static,
) -> Result<RevokeToken, ()>
pub fn on_despawn<Marker>( &mut self, entity: Entity, reactor: impl IntoSystem<(), (), Marker> + Send + Sync + 'static, ) -> Result<RevokeToken, ()>
Register a reactor to an entity despawn.
Despawn reactors are one-shot systems and will automatically clean themselves up when the entity despawns.
Returns Err
if the entity does not exist.
Example:
rcommands.on_despawn(entity, my_reactor_system).expect("entity is missing");
Sourcepub fn once<I, Marker>(
&mut self,
triggers: impl ReactionTriggerBundle<I>,
reactor: impl IntoSystem<I, (), Marker> + Send + Sync + 'static,
) -> RevokeToken
pub fn once<I, Marker>( &mut self, triggers: impl ReactionTriggerBundle<I>, reactor: impl IntoSystem<I, (), Marker> + Send + Sync + 'static, ) -> RevokeToken
Register a one-off reactor triggered by ECS changes.
Similar to Self::on
except the reaction will run exactly once then get cleaned up.
Example:
// The reactor will run on the first mutation of either MyRes or MyComponent.
rcommands.once((resource_mutation::<MyRes>(), component_mutation::<MyComponent>()), my_reactor_system);
Trait Implementations§
Source§impl SystemParam for ReactCommands<'_, '_>
impl SystemParam for ReactCommands<'_, '_>
Source§type Item<'w, 's> = ReactCommands<'w, 's>
type Item<'w, 's> = ReactCommands<'w, 's>
Self
, instantiated with new lifetimes. Read moreSource§fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State
World
access used by this SystemParam
and creates a new instance of this param’s State
.Source§fn new_archetype(
state: &mut Self::State,
archetype: &Archetype,
system_meta: &mut SystemMeta,
)
fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, )
Archetype
, registers the components accessed by this SystemParam
(if applicable).Source§fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World)
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World)
SystemParam
’s state.
This is used to apply Commands
during apply_deferred
.Source§unsafe fn get_param<'w, 's>(
state: &'s mut Self::State,
system_meta: &SystemMeta,
world: UnsafeWorldCell<'w>,
change_tick: Tick,
) -> Self::Item<'w, 's>
unsafe fn get_param<'w, 's>( state: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's>
SystemParamFunction
. Read moreimpl<'w, 's> ReadOnlySystemParam for ReactCommands<'w, 's>where
Commands<'w, 's>: ReadOnlySystemParam,
ResMut<'w, ReactCache>: ReadOnlySystemParam,
Res<'w, AutoDespawner>: ReadOnlySystemParam,
Auto Trait Implementations§
impl<'w, 's> Freeze for ReactCommands<'w, 's>
impl<'w, 's> !RefUnwindSafe for ReactCommands<'w, 's>
impl<'w, 's> Send for ReactCommands<'w, 's>
impl<'w, 's> Sync for ReactCommands<'w, 's>
impl<'w, 's> Unpin for ReactCommands<'w, 's>
impl<'w, 's> !UnwindSafe for ReactCommands<'w, 's>
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
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§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
.Source§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
.Source§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.Source§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.