Merge 7332ca3c48
into 877d278785
This commit is contained in:
commit
26fe5b2b13
@ -50,8 +50,9 @@ critical-section = [
|
||||
# bevy
|
||||
bevy_app = { path = "../bevy_app", version = "0.17.0-dev", default-features = false }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.17.0-dev", default-features = false }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.17.0-dev", default-features = false, optional = true }
|
||||
bevy_log = { path = "../bevy_log", version = "0.17.0-dev", default-features = false }
|
||||
bevy_platform = { path = "../bevy_platform", version = "0.17.0-dev", default-features = false }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.17.0-dev", default-features = false, optional = true }
|
||||
|
||||
# other
|
||||
crossbeam-channel = { version = "0.5.0", default-features = false, features = [
|
||||
|
79
crates/bevy_time/src/delayed_commands.rs
Normal file
79
crates/bevy_time/src/delayed_commands.rs
Normal file
@ -0,0 +1,79 @@
|
||||
use crate::Time;
|
||||
use alloc::boxed::Box;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_log::warn;
|
||||
use core::time::Duration;
|
||||
|
||||
/// A [`Command`] that will be executed after a specified delay has elapsed.
|
||||
///
|
||||
/// This can be helpful for scheduling actions at some point in the future.
|
||||
///
|
||||
/// This works by moving the supplied command into a component that is spawned on an entity.
|
||||
/// Delayed command entities are ticked via [`tick_delayed_commands`],
|
||||
/// which is typically run in [`First`] as part of [`TimePlugin`].
|
||||
#[derive(Component)]
|
||||
pub struct DelayedCommand {
|
||||
pub delay: Duration,
|
||||
pub command: Box<dyn Command + Send + Sync + 'static>,
|
||||
}
|
||||
|
||||
impl DelayedCommand {
|
||||
pub fn new(delay: Duration, command: impl Command + Send + Sync + 'static) -> Self {
|
||||
Self {
|
||||
delay,
|
||||
command: Box::new(command),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Command for DelayedCommand {
|
||||
/// Spawns a new entity with the [`DelayedCommand`] as a component.
|
||||
fn apply(self, world: &mut World) {
|
||||
world.spawn(self);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick_delayed_commands(
|
||||
mut commands: Commands,
|
||||
time: Res<Time>,
|
||||
mut delayed_commands: Query<(Entity, &mut DelayedCommand)>,
|
||||
) {
|
||||
let delta = time.delta();
|
||||
for (entity, mut delayed_command) in delayed_commands.iter_mut() {
|
||||
delayed_command.delay -= delta;
|
||||
if delayed_command.delay <= Duration::ZERO {
|
||||
commands.entity(entity).queue(EvaluateDelayedCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An [`EntityCommand`] that causes a delayed command to be evaluated.
|
||||
///
|
||||
/// This will send the command to the [`CommandQueue`] for execution,
|
||||
/// and clean up the entity that held the delayed command.
|
||||
struct EvaluateDelayedCommand;
|
||||
|
||||
impl EntityCommand for EvaluateDelayedCommand {
|
||||
fn apply(self, mut entity_world_mut: EntityWorldMut) -> () {
|
||||
// Take the DelayedCommand component from the entity,
|
||||
// allowing us to execute the command and clean up the entity
|
||||
// without cloning the command.
|
||||
let Some(delayed_command) = entity_world_mut.take::<DelayedCommand>() else {
|
||||
warn!(
|
||||
"Entity {} does not have a DelayedCommand component at the time of evaluation",
|
||||
entity_world_mut.id()
|
||||
);
|
||||
entity_world_mut.despawn();
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
// Clean up the entity that held the delayed command
|
||||
let entity = entity_world_mut.id();
|
||||
let world = entity_world_mut.into_world_mut();
|
||||
world.despawn(entity);
|
||||
|
||||
// Execute the delayed command
|
||||
world.commands().queue(delayed_command.command);
|
||||
}
|
||||
}
|
@ -14,6 +14,8 @@ extern crate alloc;
|
||||
|
||||
/// Common run conditions
|
||||
pub mod common_conditions;
|
||||
pub mod delayed_commands;
|
||||
|
||||
mod fixed;
|
||||
mod real;
|
||||
mod stopwatch;
|
||||
@ -86,6 +88,10 @@ impl Plugin for TimePlugin {
|
||||
.in_set(TimeSystems)
|
||||
.ambiguous_with(event_update_system),
|
||||
)
|
||||
.add_systems(
|
||||
First,
|
||||
delayed_commands::tick_delayed_commands.after(TimeSystems),
|
||||
)
|
||||
.add_systems(
|
||||
RunFixedMainLoop,
|
||||
run_fixed_main_schedule.in_set(RunFixedMainLoopSystems::FixedMainLoop),
|
||||
|
Loading…
Reference in New Issue
Block a user