Use observers for removal detection in example (#14895)

# Objective

The removal detection example shows an outdated pattern.

## Solution

Show how to do this with observers.
This commit is contained in:
Jan Hohenheim 2024-08-24 01:45:01 +02:00 committed by GitHub
parent 3ded59ed47
commit ddf466603c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,27 +1,28 @@
//! This example shows how you can know when a [`Component`] has been removed, so you can react to it. //! This example shows how you can know when a [`Component`] has been removed, so you can react to it.
//!
//! When a [`Component`] is removed from an [`Entity`], all [`Observer`] with an [`OnRemove`] trigger for
//! that [`Component`] will be notified. These observers will be called immediately after the
//! [`Component`] is removed. For more info on observers, see the
//! [observers example](https://github.com/bevyengine/bevy/blob/main/examples/ecs/observers.rs).
//!
//! Advanced users may also consider using a lifecycle hook
//! instead of an observer, as it incurs less overhead for a case like this.
//! See the [component hooks example](https://github.com/bevyengine/bevy/blob/main/examples/ecs/component_hooks.rs).
use bevy::prelude::*; use bevy::prelude::*;
fn main() { fn main() {
// Information regarding removed `Component`s is discarded at the end of each frame, so you need
// to react to the removal before the frame is over.
//
// Also, `Components` are removed via a `Command`, which are not applied immediately.
// So you need to react to the removal at some stage after `apply_deferred` has run,
// and the Component` is removed.
//
// With these constraints in mind we make sure to place the system that removes a `Component` in
// `Update', and the system that reacts on the removal in `PostUpdate`.
App::new() App::new()
.add_plugins(DefaultPlugins) .add_plugins(DefaultPlugins)
.add_systems(Startup, setup) .add_systems(Startup, setup)
// This system will remove a component after two seconds.
.add_systems(Update, remove_component) .add_systems(Update, remove_component)
.add_systems(PostUpdate, react_on_removal) // This observer will react to the removal of the component.
.observe(react_on_removal)
.run(); .run();
} }
// This `Struct` is just used for convenience in this example. This is the `Component` we'll be /// This `struct` is just used for convenience in this example. This is the [`Component`] we'll be
// giving to the `Entity` so we have a `Component` to remove in `remove_component()`. /// giving to the `Entity` so we have a [`Component`] to remove in `remove_component()`.
#[derive(Component)] #[derive(Component)]
struct MyComponent; struct MyComponent;
@ -50,12 +51,10 @@ fn remove_component(
} }
} }
fn react_on_removal(mut removed: RemovedComponents<MyComponent>, mut query: Query<&mut Sprite>) { fn react_on_removal(trigger: Trigger<OnRemove, MyComponent>, mut query: Query<&mut Sprite>) {
// `RemovedComponents<T>::read()` returns an iterator with the `Entity`s that had their // The `OnRemove` trigger was automatically called on the `Entity` that had its `MyComponent` removed.
// `Component` `T` (in this case `MyComponent`) removed at some point earlier during the frame. let entity = trigger.entity();
for entity in removed.read() {
if let Ok(mut sprite) = query.get_mut(entity) { if let Ok(mut sprite) = query.get_mut(entity) {
sprite.color = Color::srgb(0.5, 1., 1.); sprite.color = Color::srgb(0.5, 1., 1.);
} }
}
} }