-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
Description
Bevy version
0.10.1
What you did
I'm working on a game and have recently found that my systems sometimes run in a wrong order, although chained (with chain()). I tried to reproduce this from the ground but failed to achieve the same behavior, however I hit something very similar (the code below):
Here's the code that runs 3 identical and chained systems on the same event
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(MinimalPlugins)
.add_state::<AppState>()
.add_event::<MyEvent>()
.init_resource::<EventTriggerState>()
.add_system(event_trigger.run_if(in_state(AppState::Events)))
.add_systems(
(
event_listener1,
event_listener2,
event_listener3,
)
.chain()
.distributive_run_if(on_event::<MyEvent>())
.in_set(OnUpdate(AppState::Events))
)
.run();
}
#[derive(States, Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub enum AppState {
#[default]
Events,
}
struct MyEvent;
#[derive(Resource)]
struct EventTriggerState {
event_timer: Timer,
}
impl Default for EventTriggerState {
fn default() -> Self {
EventTriggerState {
event_timer: Timer::from_seconds(1.0, TimerMode::Repeating),
}
}
}
// sends MyEvent every second
fn event_trigger(
time: Res<Time>,
mut my_events: EventWriter<MyEvent>,
mut state: ResMut<EventTriggerState>,
) {
if state.event_timer.tick(time.delta()).finished() {
my_events.send(MyEvent);
println!("========");
}
}
fn event_listener1() {
println!("system 1");
}
fn event_listener2() {
println!("system 2");
}
fn event_listener3() {
println!("system 3");
}On one of several runs it outputs the following:
========
system 2
system 3
system 1
========
system 2
system 3
system 1
========
system 2
system 3
system 1
...
It never outputs anything different from this or what is expected (123).
Introducing a state is necessary for this to reproduce (along with adding relevant .in_set(OnUpdate(AppState::Events)))
Running systems on_event is necessary as well.
I tried to simplify this code and replaced `Timer` with `thread::sleep`
use std::{thread, time};
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(MinimalPlugins)
.add_state::<AppState>()
.add_event::<MyEvent>()
.add_system(event_trigger.run_if(in_state(AppState::Events)))
.add_systems(
(
event_listener1,
event_listener2,
event_listener3,
)
.chain()
.distributive_run_if(on_event::<MyEvent>())
.in_set(OnUpdate(AppState::Events))
)
.run();
}
#[derive(States, Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub enum AppState {
#[default]
Events,
}
struct MyEvent;
// sends MyEvent every second
fn event_trigger(
mut my_events: EventWriter<MyEvent>,
) {
thread::sleep(time::Duration::from_millis(1000));
my_events.send(MyEvent);
println!("========");
}
fn event_listener1(/*mut events: EventReader<MyEvent>*/) {
println!("system 1");
}
fn event_listener2(/*mut events: EventReader<MyEvent>*/) {
println!("system 2");
}
fn event_listener3(/*mut events: EventReader<MyEvent>*/) {
println!("system 3");
}And while it exhibits the same behavior as the first code snippet, it starts to act even more weird if you uncomment event_listeners EventReader argument. Sometimes it outputs this:
========
system 2
system 3
system 1
========
system 3
system 1
system 2
========
system 1
system 2
system 3
========
system 1
system 2
system 3
========
system 1
system 2
system 3
...
And again, it never outputs anything different from this or what is expected (123). Also, I cannot reproduce this on the first code snippet utilizing timer.