bevy
bevy copied to clipboard
`NextState<T>` event gets silently dropped under specific conditions
Bevy version
bevy = "0.15.0"
What you did
Requested ResMut<NextState<T>> in system where T is a SubStates and this substate is not "active" yet.
What went wrong
System with ResMut<NextState<T>> will get executed, next state set but no state transition/warn will happen.
Additional information
This code
use std::any::type_name;
use bevy::{
log::LogPlugin,
prelude::*,
state::{app::StatesPlugin, state::FreelyMutableState},
};
fn main() {
let mut app = App::new();
app.add_plugins((MinimalPlugins, StatesPlugin, LogPlugin::default()))
.init_state::<OuterState>()
.add_sub_state::<LeftInnerState>()
.add_sub_state::<RightInnerState>()
.add_systems(Update, ping(LeftInnerState::Right).run_if(run_once))
.add_systems(OnEnter(LeftInnerState::Right), pong(LeftInnerState::Right))
.add_systems(Update, ping(RightInnerState::Left).run_if(run_once))
.add_systems(OnEnter(RightInnerState::Left),pong(RightInnerState::Left))
.add_systems(Update, warn_me.run_if(run_once));
app.update();
app.update();
app.update();
}
fn ping<S: FreelyMutableState>(next: S) -> impl FnMut(ResMut<NextState<S>>) {
move |mut next_state| {
next_state.set(next.clone());
info!("ping: {}::{:?}", type_name::<S>(), next.clone())
}
}
fn pong<S: FreelyMutableState>(from: S) -> impl FnMut() {
move || info!("pong: {}::{:?}", type_name::<S>(), from.clone())
}
#[derive(Debug, Default, States, Hash, PartialEq, Eq, Clone)]
enum OuterState {
#[default]
Left,
Right,
}
#[derive(Debug, Default, SubStates, Hash, PartialEq, Eq, Clone)]
#[source(OuterState = OuterState::Left)]
enum LeftInnerState {
#[default]
Left,
Right,
}
#[derive(Debug, Default, SubStates, Hash, PartialEq, Eq, Clone)]
#[source(OuterState = OuterState::Right)]
enum RightInnerState {
Left,
#[default]
Right,
}
fn warn_me(_: Res<State<RightInnerState>>) {}
produces this:
2024-12-02T17:07:47.826948Z INFO bevy_silent_event_drop_test: ping: bevy_silent_event_drop_test::RightInnerState::Left
2024-12-02T17:07:47.826948Z WARN bevy_ecs::system::function_system: bevy_silent_event_drop_test::warn_me did not run because it requested inaccessible system parameter Res<State<RightInnerState>>
2024-12-02T17:07:47.827291Z INFO bevy_silent_event_drop_test: ping: bevy_silent_event_drop_test::LeftInnerState::Right
2024-12-02T17:07:47.827927Z INFO bevy_silent_event_drop_test: pong: bevy_silent_event_drop_test::LeftInnerState::Right
From that 1 line is missing:
INFO pong from bevy_silent_event_drop_test::RightInnerState::LeftorWARN bevy_ecs::system::function_system: bevy_silent_event_drop_test::ping did not run because it requested inaccessible system parameter ResMut<NextState<RightInnerState>>orWARN received next state event for subsstate which is currently inaccessible due to it's parent not being in right state or something
It should be 2 or 3.