From 43f92d3da5a5e31e607d275583b6d633f5d9b774 Mon Sep 17 00:00:00 2001 From: jabu Date: Thu, 2 Mar 2023 12:53:54 +0000 Subject: [PATCH] Add timer-based common run conditions (`on_timer` and `on_fixed_timer`) (#7866) # Objective Fixes #7864 ## Solution Add the run conditions described in the issue. Also needed to add `bevy` as a dev dependency to `bevy_time` so the doctests can run. --- ## Changelog - Add `on_timer` and `on_fixed_timer` run conditions --- crates/bevy_time/src/common_conditions.rs | 76 +++++++++++++++++++++++ crates/bevy_time/src/lib.rs | 2 + 2 files changed, 78 insertions(+) create mode 100644 crates/bevy_time/src/common_conditions.rs diff --git a/crates/bevy_time/src/common_conditions.rs b/crates/bevy_time/src/common_conditions.rs new file mode 100644 index 0000000000000..357f83cbe2dcc --- /dev/null +++ b/crates/bevy_time/src/common_conditions.rs @@ -0,0 +1,76 @@ +use crate::{fixed_timestep::FixedTime, Time, Timer, TimerMode}; +use bevy_ecs::system::Res; +use bevy_utils::Duration; + +/// Run condition that is active on a regular time interval, using [`Time`] to advance +/// the timer. +/// +/// If used for a fixed timestep system, use [`on_fixed_timer`] instead. +/// +/// ```rust,no_run +/// # use bevy_app::{App, IntoSystemAppConfig, NoopPluginGroup as DefaultPlugins, PluginGroup}; +/// # use bevy_ecs::schedule::IntoSystemConfig; +/// # use bevy_utils::Duration; +/// # use bevy_time::common_conditions::on_timer; +/// fn main() { +/// App::new() +/// .add_plugins(DefaultPlugins) +/// .add_system(tick.run_if(on_timer(Duration::from_secs(1)))) +/// .run(); +/// } +/// fn tick() { +/// // ran once a second +/// } +/// ``` +/// +/// Note that this does **not** guarantee that systems will run at exactly the +/// specified interval. If delta time is larger than the specified `duration` then +/// the system will only run once even though the timer may have completed multiple +/// times. This condition should only be used with large time durations (relative to +/// delta time). +/// +/// For more accurate timers, use the [`Timer`] class directly (see +/// [`Timer::times_finished_this_tick`] to address the problem mentioned above), or +/// use fixed timesteps that allow systems to run multiple times per frame. +pub fn on_timer(duration: Duration) -> impl FnMut(Res