Skip to content

Commit

Permalink
Add TimeUpdateStrategy resource for manual Time updating (#6159)
Browse files Browse the repository at this point in the history
# Objective

- Addresses #6146 by allowing manual `Time` updating

## Solution
- Create `TimeUpdateStrategy` config resource
- Allow users to specify a manual `Instant/Duration` or leave as default (automatic)
- Get resource in `bevy_time::time_system`and update time with desired value
---

## Changelog

- Add `TimeUpdateStrategy` resource
- Update `bevy_time::time_system` to use optional manual values

Co-authored-by: BuildTools <unconfigured@null.spigotmc.org>
Co-authored-by: Lucidus115 <92978847+Lucidus115@users.noreply.github.com>
  • Loading branch information
3 people committed Oct 24, 2022
1 parent 9663115 commit 13b9da7
Showing 1 changed file with 31 additions and 8 deletions.
39 changes: 31 additions & 8 deletions crates/bevy_time/src/lib.rs
Expand Up @@ -9,8 +9,8 @@ pub use stopwatch::*;
pub use time::*;
pub use timer::*;

use bevy_ecs::system::{Local, Res, ResMut};
use bevy_utils::{tracing::warn, Instant};
use bevy_ecs::system::{Res, ResMut};
use bevy_utils::{tracing::warn, Duration, Instant};
use crossbeam_channel::{Receiver, Sender};

pub mod prelude {
Expand All @@ -34,6 +34,7 @@ pub struct TimeSystem;
impl Plugin for TimePlugin {
fn build(&self, app: &mut App) {
app.init_resource::<Time>()
.init_resource::<TimeUpdateStrategy>()
.init_resource::<FixedTimesteps>()
.register_type::<Timer>()
.register_type::<Time>()
Expand All @@ -44,6 +45,20 @@ impl Plugin for TimePlugin {
}
}

/// Configuration resource used to determine how the time system should run.
///
/// For most cases, [`TimeUpdateStrategy::Automatic`] is fine. When writing tests, dealing with networking, or similar
/// you may prefer to set the next [`Time`] value manually.
#[derive(Resource, Default)]
pub enum TimeUpdateStrategy {
#[default]
Automatic,
// Update [`Time`] with an exact `Instant` value
ManualInstant(Instant),
// Update [`Time`] with the current time + a specified `Duration`
ManualDuration(Duration),
}

/// Channel resource used to receive time from render world
#[derive(Resource)]
pub struct TimeReceiver(pub Receiver<Instant>);
Expand All @@ -64,18 +79,26 @@ pub fn create_time_channels() -> (TimeSender, TimeReceiver) {
/// there to this system through channels. Otherwise the time is updated in this system.
fn time_system(
mut time: ResMut<Time>,
update_strategy: Res<TimeUpdateStrategy>,
time_recv: Option<Res<TimeReceiver>>,
mut has_received_time: Local<bool>,
) {
if let Some(time_recv) = time_recv {
let new_time = if let Some(time_recv) = time_recv {
// TODO: Figure out how to handle this when using pipelined rendering.
if let Ok(new_time) = time_recv.0.try_recv() {
time.update_with_instant(new_time);
*has_received_time = true;
} else if *has_received_time {
new_time
} else {
warn!("time_system did not receive the time from the render world! Calculations depending on the time may be incorrect.");
Instant::now()
}
} else {
time.update();
Instant::now()
};

match update_strategy.as_ref() {
TimeUpdateStrategy::Automatic => time.update_with_instant(new_time),
TimeUpdateStrategy::ManualInstant(instant) => time.update_with_instant(*instant),
TimeUpdateStrategy::ManualDuration(duration) => {
time.update_with_instant(Instant::now() + *duration);
}
}
}

0 comments on commit 13b9da7

Please sign in to comment.