diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index a169cda57fca8..77303f7695272 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -190,6 +190,7 @@ impl Default for App { app.init_resource::(); app.add_plugins(MainSchedulePlugin); + app.add_event::(); #[cfg(feature = "bevy_ci_testing")] diff --git a/crates/bevy_ecs/src/event.rs b/crates/bevy_ecs/src/event.rs index ef594fcf00f53..37a6f98532e9d 100644 --- a/crates/bevy_ecs/src/event.rs +++ b/crates/bevy_ecs/src/event.rs @@ -733,8 +733,30 @@ impl<'a, E: Event> ExactSizeIterator for EventIteratorWithId<'a, E> { } } -/// A system that calls [`Events::update`] once per frame. -pub fn event_update_system(mut events: ResMut>) { +#[doc(hidden)] +#[derive(Resource, Default)] +pub struct EventUpdateSignal(bool); + +/// A system that queues a call to [`Events::update`]. +pub fn event_queue_update_system(signal: Option>) { + if let Some(mut s) = signal { + s.0 = true; + } +} + +/// A system that calls [`Events::update`]. +pub fn event_update_system( + signal: Option>, + mut events: ResMut>, +) { + if let Some(mut s) = signal { + // If we haven't got a signal to update the events, but we *could* get such a signal + // return early and update the events later. + if !std::mem::replace(&mut s.0, false) { + return; + } + } + events.update(); } diff --git a/crates/bevy_time/src/lib.rs b/crates/bevy_time/src/lib.rs index 2d47acf06b60c..d9b110bbe27a7 100644 --- a/crates/bevy_time/src/lib.rs +++ b/crates/bevy_time/src/lib.rs @@ -18,11 +18,6 @@ pub use time::*; pub use timer::*; pub use virt::*; -use bevy_ecs::system::{Res, ResMut}; -use bevy_utils::{tracing::warn, Duration, Instant}; -pub use crossbeam_channel::TrySendError; -use crossbeam_channel::{Receiver, Sender}; - pub mod prelude { //! The Bevy Time Prelude. #[doc(hidden)] @@ -30,7 +25,11 @@ pub mod prelude { } use bevy_app::{prelude::*, RunFixedUpdateLoop}; +use bevy_ecs::event::{event_queue_update_system, EventUpdateSignal}; use bevy_ecs::prelude::*; +use bevy_utils::{tracing::warn, Duration, Instant}; +pub use crossbeam_channel::TrySendError; +use crossbeam_channel::{Receiver, Sender}; /// Adds time functionality to Apps. #[derive(Default)] @@ -60,6 +59,10 @@ impl Plugin for TimePlugin { ) .add_systems(RunFixedUpdateLoop, run_fixed_update_schedule); + // ensure the events are not dropped until `FixedUpdate` systems can observe them + app.init_resource::() + .add_systems(FixedUpdate, event_queue_update_system); + #[cfg(feature = "bevy_ci_testing")] if let Some(ci_testing_config) = app .world