Skip to content

Commit bc72ced

Browse files
authored
Make initial StateTransition run before PreStartup (#14208)
# Objective - Fixes #14206 ## Solution - Run initial `StateTransition` as a startup schedule before `PreStartup`, instead of running it inside `Startup` as an exclusive system. Related discord discussion: https://discord.com/channels/691052431525675048/692572690833473578/1259543775668207678 ## Testing Reproduction now works correctly: ```rs use bevy::prelude::*; #[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)] enum AppState { #[default] Menu, InGame, } fn main() { App::new() .add_plugins(DefaultPlugins) .init_state::<AppState>() .add_systems(Startup, setup) .add_systems(OnEnter(AppState::Menu), enter_menu_state) .run(); } fn setup(mut next_state: ResMut<NextState<AppState>>) { next_state.set(AppState::Menu); } fn enter_menu_state() { println!("Entered menu state"); } ``` ![image](https://github.com/bevyengine/bevy/assets/13040204/96d7a533-c439-4c0b-8f15-49f620903ce1) --- ## Changelog - Initial `StateTransition` runs before `PreStartup` instead of inside `Startup`.
1 parent 6e8d43a commit bc72ced

File tree

3 files changed

+16
-34
lines changed

3 files changed

+16
-34
lines changed

crates/bevy_state/src/app.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
use bevy_app::{App, MainScheduleOrder, Plugin, PreUpdate, Startup, SubApp};
2-
use bevy_ecs::{
3-
event::Events,
4-
schedule::{IntoSystemConfigs, ScheduleLabel},
5-
world::FromWorld,
6-
};
1+
use bevy_app::{App, MainScheduleOrder, Plugin, PreStartup, PreUpdate, SubApp};
2+
use bevy_ecs::{event::Events, schedule::IntoSystemConfigs, world::FromWorld};
73
use bevy_utils::{tracing::warn, warn_once};
84

95
use crate::state::{
@@ -221,7 +217,8 @@ impl Plugin for StatesPlugin {
221217
fn build(&self, app: &mut App) {
222218
let mut schedule = app.world_mut().resource_mut::<MainScheduleOrder>();
223219
schedule.insert_after(PreUpdate, StateTransition);
224-
setup_state_transitions_in_world(app.world_mut(), Some(Startup.intern()));
220+
schedule.insert_startup_before(PreStartup, StateTransition);
221+
setup_state_transitions_in_world(app.world_mut());
225222
}
226223
}
227224

crates/bevy_state/src/state/mod.rs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ pub use transitions::*;
1919
mod tests {
2020
use bevy_ecs::event::EventRegistry;
2121
use bevy_ecs::prelude::*;
22-
use bevy_ecs::schedule::ScheduleLabel;
2322
use bevy_state_macros::States;
2423
use bevy_state_macros::SubStates;
2524

@@ -64,7 +63,7 @@ mod tests {
6463

6564
world.insert_resource(schedules);
6665

67-
setup_state_transitions_in_world(&mut world, None);
66+
setup_state_transitions_in_world(&mut world);
6867

6968
world.run_schedule(StateTransition);
7069
assert_eq!(world.resource::<State<SimpleState>>().0, SimpleState::A);
@@ -120,7 +119,7 @@ mod tests {
120119

121120
world.insert_resource(schedules);
122121

123-
setup_state_transitions_in_world(&mut world, None);
122+
setup_state_transitions_in_world(&mut world);
124123

125124
world.run_schedule(StateTransition);
126125
assert_eq!(world.resource::<State<SimpleState>>().0, SimpleState::A);
@@ -180,7 +179,7 @@ mod tests {
180179

181180
world.insert_resource(schedules);
182181

183-
setup_state_transitions_in_world(&mut world, None);
182+
setup_state_transitions_in_world(&mut world);
184183

185184
world.run_schedule(StateTransition);
186185
assert_eq!(world.resource::<State<SimpleState>>().0, SimpleState::A);
@@ -275,7 +274,7 @@ mod tests {
275274

276275
world.insert_resource(schedules);
277276

278-
setup_state_transitions_in_world(&mut world, None);
277+
setup_state_transitions_in_world(&mut world);
279278

280279
world.run_schedule(StateTransition);
281280
assert_eq!(world.resource::<State<SimpleState>>().0, SimpleState::A);
@@ -354,9 +353,6 @@ mod tests {
354353
}
355354
}
356355

357-
#[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash)]
358-
struct Startup;
359-
360356
#[test]
361357
fn computed_state_transitions_are_produced_correctly() {
362358
let mut world = World::new();
@@ -367,7 +363,7 @@ mod tests {
367363
world.init_resource::<State<SimpleState2>>();
368364
world.init_resource::<Schedules>();
369365

370-
setup_state_transitions_in_world(&mut world, Some(Startup.intern()));
366+
setup_state_transitions_in_world(&mut world);
371367

372368
let mut schedules = world
373369
.get_resource_mut::<Schedules>()
@@ -431,7 +427,7 @@ mod tests {
431427

432428
world.init_resource::<ComputedStateTransitionCounter>();
433429

434-
setup_state_transitions_in_world(&mut world, None);
430+
setup_state_transitions_in_world(&mut world);
435431

436432
assert_eq!(world.resource::<State<SimpleState>>().0, SimpleState::A);
437433
assert_eq!(world.resource::<State<SimpleState2>>().0, SimpleState2::A1);
@@ -508,7 +504,7 @@ mod tests {
508504
#[test]
509505
fn same_state_transition_should_emit_event_and_not_run_schedules() {
510506
let mut world = World::new();
511-
setup_state_transitions_in_world(&mut world, None);
507+
setup_state_transitions_in_world(&mut world);
512508
EventRegistry::register_event::<StateTransitionEvent<SimpleState>>(&mut world);
513509
world.init_resource::<State<SimpleState>>();
514510
let mut schedules = world.resource_mut::<Schedules>();
@@ -568,7 +564,7 @@ mod tests {
568564
SubState::register_sub_state_systems(&mut apply_changes);
569565
schedules.insert(apply_changes);
570566
world.insert_resource(schedules);
571-
setup_state_transitions_in_world(&mut world, None);
567+
setup_state_transitions_in_world(&mut world);
572568

573569
world.insert_resource(NextState::Pending(SimpleState::B(true)));
574570
world.run_schedule(StateTransition);
@@ -599,7 +595,7 @@ mod tests {
599595
TestComputedState::register_computed_state_systems(&mut apply_changes);
600596
schedules.insert(apply_changes);
601597
world.insert_resource(schedules);
602-
setup_state_transitions_in_world(&mut world, None);
598+
setup_state_transitions_in_world(&mut world);
603599

604600
world.insert_resource(NextState::Pending(SimpleState::B(true)));
605601
world.run_schedule(StateTransition);
@@ -651,7 +647,7 @@ mod tests {
651647
#[test]
652648
fn check_transition_orders() {
653649
let mut world = World::new();
654-
setup_state_transitions_in_world(&mut world, None);
650+
setup_state_transitions_in_world(&mut world);
655651
EventRegistry::register_event::<StateTransitionEvent<SimpleState>>(&mut world);
656652
EventRegistry::register_event::<StateTransitionEvent<SubState>>(&mut world);
657653
EventRegistry::register_event::<StateTransitionEvent<TransitionTestingComputedState>>(

crates/bevy_state/src/state/transitions.rs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ use std::{marker::PhantomData, mem};
22

33
use bevy_ecs::{
44
event::{Event, EventReader, EventWriter},
5-
schedule::{
6-
InternedScheduleLabel, IntoSystemSetConfigs, Schedule, ScheduleLabel, Schedules, SystemSet,
7-
},
5+
schedule::{IntoSystemSetConfigs, Schedule, ScheduleLabel, Schedules, SystemSet},
86
system::{Commands, In, ResMut},
97
world::World,
108
};
@@ -182,10 +180,7 @@ pub(crate) fn internal_apply_state_transition<S: States>(
182180
///
183181
/// Runs automatically when using `App` to insert states, but needs to
184182
/// be added manually in other situations.
185-
pub fn setup_state_transitions_in_world(
186-
world: &mut World,
187-
startup_label: Option<InternedScheduleLabel>,
188-
) {
183+
pub fn setup_state_transitions_in_world(world: &mut World) {
189184
let mut schedules = world.get_resource_or_insert_with(Schedules::default);
190185
if schedules.contains(StateTransition) {
191186
return;
@@ -201,12 +196,6 @@ pub fn setup_state_transitions_in_world(
201196
.chain(),
202197
);
203198
schedules.insert(schedule);
204-
205-
if let Some(startup) = startup_label {
206-
schedules.add_systems(startup, |world: &mut World| {
207-
let _ = world.try_run_schedule(StateTransition);
208-
});
209-
}
210199
}
211200

212201
/// Returns the latest state transition event of type `S`, if any are available.

0 commit comments

Comments
 (0)