Unexpected behavior using `States` and `Event`s
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
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::()
.add_event::()
.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::)))
.add_systems(OnEnter(Phases::Phase2), send_event2)
.add_systems(Update, end_phase2
.run_if(in_state(Phases::Phase2).and(on_event::)))
.run();
}
fn start(mut next_state: ResMut>) {
next_state.set(Phases::Phase1);
}
fn send_event1(
mut event: EventWriter,
) {
println!("Sending event 1");
event.send_default();
}
fn end_phase1(
mut event: EventReader,
mut next_state: ResMut>,
) {
for _ in event.read() {
println!("Ending phase 1");
next_state.set(Phases::Phase2);
}
}
fn send_event2(
mut event: EventWriter,
time: Res
fn end_phase2(
mut event: EventReader,
mut next_state: ResMut>,
) {
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!
Contributor guide
Research direction
Start by running the complete Rust reproduction from the issue and compare the scheduling of send_event1, end_phase1, send_event2, and end_phase2 across the Phases states. Trace how on_event:: and EventReader handle events during state transitions; done means determining whether the observed Phase2 runs are expected and adding a focused regression test or documenting the cause.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- game-dev
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100