Bevy 时间

本文我们将会介绍三种时间相关的工具------TimeTimerStopwatch、,也就是游戏时间、定时器和秒表。

游戏时间

Time是获取游戏时间的主要全局资源,我们可以在任何系统中访问时间,如果我们需要时间信息,就一定要通过TimeBevy会在每一帧的最开始更新时间。

delta 时间

最常见的用法就是获取delta time ------当前帧与上一帧的时间间隔。该时间可以体现游戏帧率有多快(想象一下30帧和120帧的时间间隔),因此我们一般通过这个时间来更新移动和动画等内容。这样做可以确保大家以相同的速度运行,无论游戏的帧率有多高。

rust 复制代码
fn asteroids_fly(
    time: Res<Time>,
    mut q: Query<&mut Transform, With<Player>>,
) {
    for mut transform in q.iter_mut() {
        // 沿X轴以每秒10个单位的速度移动玩家
        transform.translation.x += 10.0 * time.delta_seconds();
    }
}

总运行时间

我们还可以通过Time获取到自游戏启动以来的总运行时间:

rust 复制代码
fn elapsed_info(
    time: Res<Time>,
) {
    info!("Elapsed Time: {:?}", time.elapsed_secs());
}

定时器

Timer可以用于定时器相关逻辑,例如检测一段时间间隔。Timer有两种类型:一次性(Once)和可重复(Repeating)的。

Timer需要我们手动计时,即通过tickTimer累计时间。任何类型的Timer都可以重置reset

使用just_finished检测时间是否达到设定值:

rust 复制代码
// 定义一个一次性的计时器类型
#[derive(Component)]
struct OnceTimer(Timer);

// 定义一个可循环使用的计时器类型
#[derive(Component)]
struct RepeatingTimer(Timer);

// 设定计时器,添加计时器到系统
fn set_up_timer(
    mut commands: Commands,
) {
    // 设定一个一次性计时器,3秒后触发
    commands.spawn(OnceTimer(Timer::new(Duration::from_secs(3), TimerMode::Once)));
    // 设定一个可重复的计时器,每秒触发一次
    commands.spawn(RepeatingTimer(Timer::new(Duration::from_secs(1), TimerMode::Repeating)));
}

// 更新计时器
fn update_timer(
    time: Res<Time>,
    mut once_timer: Query<&mut OnceTimer>,
    mut repeating_timer: Query<&mut RepeatingTimer>,
) {
    // 获取 delta 时间
    let delta = time.delta();
    once_timer.iter_mut().for_each(|mut timer| {
        // 步进计时器
        timer.0.tick(delta);
        // 检查计时器是否达到设定的时间点
        if timer.0.just_finished() {
            info!("Once timer just finished");
        }
    });

    repeating_timer.iter_mut().for_each(|mut timer| {
        timer.0.tick(delta);
        if timer.0.just_finished() {
            info!("Repeating timer just finished");
        }
    });
}
rust 复制代码
// other code...
.add_systems(Startup, set_up_timer)
.add_systems(Update, update_timer)
// other code...

我们看下输出结果:

makefile 复制代码
2025-03-17T01:30:53.968213Z  INFO time: Repeating timer just finished
2025-03-17T01:30:54.968752Z  INFO time: Repeating timer just finished
2025-03-17T01:30:55.969461Z  INFO time: Once timer just finished
2025-03-17T01:30:55.969547Z  INFO time: Repeating timer just finished
2025-03-17T01:30:56.970133Z  INFO time: Repeating timer just finished
2025-03-17T01:30:57.971532Z  INFO time: Repeating timer just finished
2025-03-17T01:30:58.971745Z  INFO time: Repeating timer just finished
2025-03-17T01:30:59.972249Z  INFO time: Repeating timer just finished
2025-03-17T01:31:00.957014Z  INFO time: Repeating timer just finished

一次性的计时器在3秒触发,后续不再触发。

可重复计时器会每秒都出发。

如果我们想让一次性定时器再次出发,可以使用reset重置定时器。

rust 复制代码
fn reset_once_timer(
    mut once_timer: Query<&mut OnceTimer>,
) {
    once_timer.iter_mut().for_each(|mut timer| {
        // 重置定时器
        timer.0.reset();
    });
}

当定时器重置之后,定时器又会重新累计时间。

秒表

秒表的用法和定时器Timer类似,只不过秒表的主要作用是用于跟踪从过去的某个时间点到现在的累计时间(想象一下现实生活中秒表用于记录发令枪发令开始到运动员到达终点的时间间隔)。

他们的大致区别可以概括为:Stopwatch专注于记录时间累计值(如技能冷却剩余时间),而Timer更适合周期性触发事件(如每秒恢复生命值)。

rust 复制代码
#[derive(Component)]
struct RunWatch(Stopwatch);

// 生成秒表
fn setup_watch(
    mut commands: Commands,
) {
    commands.spawn(RunWatch(Stopwatch::new()));
}

// 秒表相关逻辑
fn run_watch(
    time: Res<Time>,
    mut watch: Query<&mut RunWatch>,
    key_input:Res<ButtonInput<KeyCode>>
) {
   
    watch.iter_mut().for_each(|mut run| {
        // 秒表的时间累计
        run.0.tick(time.delta());
        if key_input.just_pressed(KeyCode::Enter) {
            // 打印秒表的累计时间
            info!("time gone: {}", run.0.elapsed_secs());
        }
    })
}
相关推荐
程序员老刘2 小时前
假如Flutter用Rust,你也写不出更快的App
flutter·rust·dart
优梦创客4 小时前
3 天搞定微小游戏上架!独立开发者副业赚钱全攻略(附选题 / 技术 / 运营干货)
微信·教程·小游戏·游戏开发
h***8564 小时前
Rust在Web中的前端开发
开发语言·前端·rust
Rust语言中文社区5 小时前
【Rust日报】 walrus:分布式消息流平台,比 Kafka 快
开发语言·分布式·后端·rust·kafka
UWA7 小时前
如何排查优化URP内置Shader冗余
性能优化·memory·游戏开发
武子康7 小时前
AI研究-133 Java vs Kotlin/Go/Rust/Python/Node:2025 详细对比分析 定位与取舍指南
java·javascript·python·golang·rust·kotlin·node
陈尕六8 小时前
从零开始的 Godot 之旅 — EP11:初识瓦片地图
godot·游戏开发
mit6.8248 小时前
C 语言仓库引入 Rust: MCUboot 为例
开发语言·rust
星释8 小时前
Rust 练习册 99:让数字开口说话
开发语言·后端·rust
我发在否9 小时前
Rust > 牛客OJ在线编程常见输入输出练习场
算法·rust