Skip to content

Commit

Permalink
Only trigger state transitons if next_state != old_state (#8359)
Browse files Browse the repository at this point in the history
# Objective

Fix #8191.

Currently, a state transition will be triggered whenever the `NextState`
resource has a value, even if that "transition" is to the same state as
the previous one. This caused surprising/meaningless behavior, such as
the existence of an `OnTransition { from: A, to: A }` schedule.

## Solution

State transition schedules now only run if the new state is not equal to
the old state. Change detection works the same way, only being triggered
when the states compare not equal.

---

## Changelog

- State transition schedules are no longer run when transitioning to and
from the same state.

## Migration Guide

State transitions are now only triggered when the exited and entered
state differ. This means that if the world is currently in state `A`,
the `OnEnter(A)` schedule (or `OnExit`) will no longer be run if you
queue up a state transition to the same state `A`.
  • Loading branch information
JoJoJet authored Apr 12, 2023
1 parent d623731 commit 7ec8900
Showing 1 changed file with 13 additions and 11 deletions.
24 changes: 13 additions & 11 deletions crates/bevy_ecs/src/schedule/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,16 +129,18 @@ pub fn apply_state_transition<S: States>(world: &mut World) {
if let Some(entered) = next_state_resource.bypass_change_detection().0.take() {
next_state_resource.set_changed();

let exited = mem::replace(&mut world.resource_mut::<State<S>>().0, entered.clone());

// Try to run the schedules if they exist.
world.try_run_schedule(OnExit(exited.clone())).ok();
world
.try_run_schedule(OnTransition {
from: exited,
to: entered.clone(),
})
.ok();
world.try_run_schedule(OnEnter(entered)).ok();
let mut state_resource = world.resource_mut::<State<S>>();
if *state_resource != entered {
let exited = mem::replace(&mut state_resource.0, entered.clone());
// Try to run the schedules if they exist.
world.try_run_schedule(OnExit(exited.clone())).ok();
world
.try_run_schedule(OnTransition {
from: exited,
to: entered.clone(),
})
.ok();
world.try_run_schedule(OnEnter(entered)).ok();
}
}
}

0 comments on commit 7ec8900

Please sign in to comment.