Open
Description
Bevy version
0.15.3
What you did
use bevy::prelude::*;
#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)]
pub enum Phases {
#[default]
None,
Phase1,
Phase2,
}
#[derive(Event, Debug, Default)]
pub struct AnEvent;
#[derive(Resource, Debug)]
struct ChangeDirectionTimer {
timer: Timer,
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_state::<Phases>()
.add_event::<AnEvent>()
.insert_resource(ChangeDirectionTimer {
timer: Timer::from_seconds(1., TimerMode::Once),
})
.add_systems(Startup, start)
.add_systems(OnEnter(Phases::Phase1), send_event1)
.add_systems(Update, end_phase1
.run_if(in_state(Phases::Phase1).and(on_event::<AnEvent>)))
.add_systems(OnEnter(Phases::Phase2), send_event2)
.add_systems(Update, end_phase2
.run_if(in_state(Phases::Phase2).and(on_event::<AnEvent>)))
.run();
}
fn start(mut next_state: ResMut<NextState<Phases>>) {
next_state.set(Phases::Phase1);
}
fn send_event1(
mut event: EventWriter<AnEvent>,
) {
println!("Sending event 1");
event.send_default();
}
fn end_phase1(
mut event: EventReader<AnEvent>,
mut next_state: ResMut<NextState<Phases>>,
) {
for _ in event.read() {
println!("Ending phase 1");
next_state.set(Phases::Phase2);
}
}
fn send_event2(
mut event: EventWriter<AnEvent>,
time: Res<Time>,
mut timer: ResMut<ChangeDirectionTimer>,
) {
timer.timer.tick(time.delta());
if timer.timer.just_finished() {
println!("Sending event 2");
event.send_default();
}
}
fn end_phase2(
mut event: EventReader<AnEvent>,
mut next_state: ResMut<NextState<Phases>>,
) {
for _ in event.read() {
println!("Ending phase 2");
next_state.set(Phases::None);
}
}
What went wrong
The output of this code is:
Sending event 1
Ending phase 1
Ending phase 2
As the system end_phase2
only runs in the Phase2
state, it should be triggered by the delayed event 2, but it's like it is triggered still by the first event.
This is confirmed by commenting out the if
statement in send_event2
, which results in:
Sending event 1
Ending phase 1
Sending event 2
Ending phase 2
Ending phase 2
So end_phase2
is actually triggered twice despite the first event is triggered in another state with respect to the one during which end_phase2
should be running.
Additional information
Am I missing something or is it a bug?
Thanks!