Add TimeUpdateStrategy resource for manual Time updating (#6159)
# 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>
This commit is contained in:
parent
9066d51420
commit
f7d3fbc7d5
@ -9,8 +9,8 @@ pub use stopwatch::*;
|
|||||||
pub use time::*;
|
pub use time::*;
|
||||||
pub use timer::*;
|
pub use timer::*;
|
||||||
|
|
||||||
use bevy_ecs::system::{Local, Res, ResMut};
|
use bevy_ecs::system::{Res, ResMut};
|
||||||
use bevy_utils::{tracing::warn, Instant};
|
use bevy_utils::{tracing::warn, Duration, Instant};
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
@ -34,6 +34,7 @@ pub struct TimeSystem;
|
|||||||
impl Plugin for TimePlugin {
|
impl Plugin for TimePlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.init_resource::<Time>()
|
app.init_resource::<Time>()
|
||||||
|
.init_resource::<TimeUpdateStrategy>()
|
||||||
.init_resource::<FixedTimesteps>()
|
.init_resource::<FixedTimesteps>()
|
||||||
.register_type::<Timer>()
|
.register_type::<Timer>()
|
||||||
.register_type::<Time>()
|
.register_type::<Time>()
|
||||||
@ -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
|
/// Channel resource used to receive time from render world
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct TimeReceiver(pub Receiver<Instant>);
|
pub struct TimeReceiver(pub Receiver<Instant>);
|
||||||
@ -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.
|
/// there to this system through channels. Otherwise the time is updated in this system.
|
||||||
fn time_system(
|
fn time_system(
|
||||||
mut time: ResMut<Time>,
|
mut time: ResMut<Time>,
|
||||||
|
update_strategy: Res<TimeUpdateStrategy>,
|
||||||
time_recv: Option<Res<TimeReceiver>>,
|
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.
|
// TODO: Figure out how to handle this when using pipelined rendering.
|
||||||
if let Ok(new_time) = time_recv.0.try_recv() {
|
if let Ok(new_time) = time_recv.0.try_recv() {
|
||||||
time.update_with_instant(new_time);
|
new_time
|
||||||
*has_received_time = true;
|
} else {
|
||||||
} else if *has_received_time {
|
|
||||||
warn!("time_system did not receive the time from the render world! Calculations depending on the time may be incorrect.");
|
warn!("time_system did not receive the time from the render world! Calculations depending on the time may be incorrect.");
|
||||||
|
Instant::now()
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user