diff --git a/crates/bevy_state/src/state_scoped.rs b/crates/bevy_state/src/state_scoped.rs index 1d224da1c13ff..ea2acdcf816db 100644 --- a/crates/bevy_state/src/state_scoped.rs +++ b/crates/bevy_state/src/state_scoped.rs @@ -67,6 +67,8 @@ where /// Despawns entities marked with [`DespawnOnExit`] when their state no /// longer matches the world state. +/// +/// If the entity has already been despawned no warning will be emitted. pub fn despawn_entities_on_exit_state( mut commands: Commands, mut transitions: MessageReader>, @@ -86,7 +88,7 @@ pub fn despawn_entities_on_exit_state( }; for (entity, binding) in &query { if binding.0 == *exited { - commands.entity(entity).despawn(); + commands.entity(entity).try_despawn(); } } } @@ -133,6 +135,8 @@ pub struct DespawnOnEnter(pub S); /// Despawns entities marked with [`DespawnOnEnter`] when their state /// matches the world state. +/// +/// If the entity has already been despawned no warning will be emitted. pub fn despawn_entities_on_enter_state( mut commands: Commands, mut transitions: MessageReader>, @@ -152,7 +156,7 @@ pub fn despawn_entities_on_enter_state( }; for (entity, binding) in &query { if binding.0 == *entered { - commands.entity(entity).despawn(); + commands.entity(entity).try_despawn(); } } } diff --git a/examples/ecs/state_scoped.rs b/examples/ecs/state_scoped.rs index 8fd4f0a6196fd..ad8d2fac38fbb 100644 --- a/examples/ecs/state_scoped.rs +++ b/examples/ecs/state_scoped.rs @@ -3,6 +3,10 @@ //! //! This pattern is useful for managing menus, levels, or other state-specific //! content that should only exist during certain states. +//! +//! If the entity was already despawned then no error will be logged. This means +//! that you don't have to worry about duplicate [`DespawnOnExit`] and +//! [`DespawnOnEnter`] components deep in your hierarchy. use bevy::prelude::*; @@ -46,6 +50,7 @@ fn on_a_enter(mut commands: Commands) { left: px(0), ..default() }, + (children![DespawnOnExit(GameState::A)]), )); } @@ -65,6 +70,10 @@ fn on_a_exit(mut commands: Commands) { left: px(500), ..default() }, + // You can apply this even when the parent has a state scoped component. + // It is unnecessary but in complex hierarchies it saves you from having to + // mentally track which components are found at the top level. + (children![DespawnOnEnter(GameState::A)]), )); } @@ -84,6 +93,7 @@ fn on_b_enter(mut commands: Commands) { left: px(0), ..default() }, + (children![DespawnOnExit(GameState::B)]), )); } @@ -103,6 +113,7 @@ fn on_b_exit(mut commands: Commands) { left: px(500), ..default() }, + (children![DespawnOnEnter(GameState::B)]), )); }