diff --git a/crates/bevy_core/src/time/timer.rs b/crates/bevy_core/src/time/timer.rs index 7322118e0558e6..dd95b2232299ec 100644 --- a/crates/bevy_core/src/time/timer.rs +++ b/crates/bevy_core/src/time/timer.rs @@ -4,32 +4,46 @@ use bevy_property::Properties; use std::time::Duration; /// Tracks elapsed time. Enters the finished state once `duration` is reached. +/// +/// Non repeating timers will stop tracking and stay in the finished state until reset. +/// Repeating timers will only be in the finished state on each tick `duration` is reached or exceeded, and can still be reset at any given point. #[derive(Clone, Debug, Default, Properties)] pub struct Timer { pub elapsed: f32, pub duration: f32, pub finished: bool, + /// Stores the last tick's finished state. Is checked against in just_finished. + prev_finished: bool, + pub repeating: bool, } impl Timer { - pub fn new(duration: Duration) -> Self { + pub fn new(duration: Duration, repeating: bool) -> Self { Timer { duration: duration.as_secs_f32(), + repeating, ..Default::default() } } - pub fn from_seconds(seconds: f32) -> Self { + pub fn from_seconds(seconds: f32, repeating: bool) -> Self { Timer { duration: seconds, + repeating, ..Default::default() } } pub fn tick(&mut self, delta: f32) { - self.elapsed = (self.elapsed + delta).min(self.duration); - if self.elapsed >= self.duration { - self.finished = true; + if self.elapsed < self.duration { + self.elapsed += delta; + } + + self.prev_finished = self.finished; + self.finished = self.elapsed >= self.duration; + + if self.repeating && self.finished { + self.elapsed = self.elapsed % self.duration; } } @@ -37,6 +51,11 @@ impl Timer { self.finished = false; self.elapsed = 0.0; } + + /// Returns true only on the exact tick elapsed time first exceeds duration. + pub fn just_finished(&self) -> bool { + (!self.prev_finished || self.repeating) && self.finished + } } pub(crate) fn timer_system(time: Res