You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++游戏模拟中如何精准每秒调用update()函数?

精准每秒调用update()的C++实现方案

Hey there! Great question—this is a super common pitfall when trying to get precise timing in game loops, and you’re already on the right track thinking about accounting for update()’s execution time. Let’s break down a few solid approaches you can use in C++ to hit that steady 1Hz call rate.

方案1:补偿式单线程循环(最直接)

This approach fixes your original loop by measuring how long update() actually takes, then adjusting the sleep duration to make up the difference. The key is to use a steady clock (not affected by system time changes) to track when the next update() should run.

代码示例:

#include <chrono>
#include <thread>
#include <iostream>

void update() {
    // 模拟update的执行时间(比如50ms)
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
    std::cout << "Update called at: " << std::chrono::duration_cast<std::chrono::seconds>(
        std::chrono::steady_clock::now().time_since_epoch()
    ).count() << "s\n";
}

int main() {
    using namespace std::chrono;

    // 初始化下一次更新的时间点
    auto next_update_time = steady_clock::now() + seconds(1);

    while (true) { // 替换成你的终止条件
        update();

        // 计算到下一次更新还需要睡眠的时间
        auto now = steady_clock::now();
        if (next_update_time <= now) {
            // 如果update执行超时,直接设置下一次时间为当前+1s(避免累积延迟)
            next_update_time = now + seconds(1);
            std::cerr << "Warning: update() took longer than 1s! Skipping missed interval.\n";
        } else {
            std::this_thread::sleep_until(next_update_time);
            next_update_time += seconds(1);
        }
    }

    return 0;
}

优缺点:

  • ✅ 单线程,无需处理复杂的同步逻辑
  • ✅ 自动补偿update()的执行时间,保证间隔稳定
  • ❌ 如果update()持续超过1秒,会丢失间隔(但代码里已经做了警告和调整)
  • ❌ 依赖系统睡眠的精度(大部分系统能做到~1ms级别的精度,足够1Hz需求)

方案2:多线程分离定时与执行

If your update() is resource-heavy or you don’t want it blocking other parts of your program, you can split the timing logic into a dedicated thread that triggers update() at precise intervals. This way, the main thread can handle input/rendering while the update thread runs independently.

代码示例:

#include <chrono>
#include <thread>
#include <mutex>
#include <iostream>
#include <atomic>

std::mutex game_state_mutex; // 保护共享游戏状态的互斥锁
std::atomic<bool> running = true;

void update() {
    std::lock_guard<std::mutex> lock(game_state_mutex); // 锁定共享资源
    // 模拟update执行时间
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    std::cout << "Update called at: " << std::chrono::duration_cast<std::chrono::seconds>(
        std::chrono::steady_clock::now().time_since_epoch()
    ).count() << "s\n";
}

void update_thread() {
    using namespace std::chrono;
    auto next_update_time = steady_clock::now() + seconds(1);

    while (running) {
        // 等待到下一次更新时间
        std::this_thread::sleep_until(next_update_time);
        
        // 执行update(如果update耗时,不会影响下一次定时)
        update();
        
        next_update_time += seconds(1);
    }
}

int main() {
    std::thread updater(update_thread);

    // 主线程可以处理其他逻辑,比如用户输入
    std::cout << "Main thread running. Press enter to exit...\n";
    std::cin.get();

    running = false;
    updater.join();

    return 0;
}

优缺点:

  • ✅ 定时逻辑不受update()执行时间影响(即使update跑1.5秒,下一次还是会准时触发)
  • ✅ 主线程可以并行处理其他任务
  • ❌ 需要处理线程同步(互斥锁、原子变量),避免数据竞争
  • ❌ 增加了程序的复杂度

关键注意事项

  • 使用std::chrono::steady_clock:不要用system_clock,因为它会被系统时间调整(比如NTP同步)打乱定时。steady_clock是单调递增的,适合计时。
  • 处理超时情况:如果update()持续超过1秒,你需要决定是跳过间隔还是延迟后续调用(上面的代码选择了跳过,避免累积延迟)。
  • 系统睡眠精度:Windows的Sleep()和POSIX的sleep()精度有限(通常10-15ms),但std::this_thread::sleep_until会使用系统最精准的定时器,足够满足1Hz的需求。如果需要更高精度(比如游戏里的60fps),可以结合高分辨率定时器,但对于1Hz来说完全没必要。

内容的提问来源于stack exchange,提问作者Yosry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:24:25