gpt4 book ai didi

c++ - Steady_Clock 在主游戏循环的更新之间跳过

转载 作者:可可西里 更新时间:2023-11-01 15:11:22 26 4
gpt4 key购买 nike

在尝试在 SFML 中制定可靠的游戏循环的过程中,我遇到了这个我似乎无法弄清楚的问题。我能够去除所有 SFML 代码,但仍然在 time.h 中看到 clock() 的问题。然后我走得更远,仍然看到使用 std::chrono::steady_clock 的问题。

问题:在某种程度上,我经常看到更新之间能够完成的工作量有所跳跃。每次更新应该花费 1/60 秒,其余时间花在 Draw() 上,尽可能多地完成绘图。有时,平局数量会无缘无故地下降到 0 或 1。这会以明显的口吃形式出现在实际应用程序中。除了“跳过”之外,完成的抽奖次数非常一致。

这是一张图片(注意更新时间的跳跃和绘制的下降): Console output of the issue

部分代码:

#include <iostream>
#include <time.h>
#include <chrono>

using namespace std;
using namespace std::chrono;

void Draw()
{
//for (int i = 0; i < 1000000; i++);
}

int main()
{
steady_clock::time_point update_time;
steady_clock::time_point update_next;
int update_rate = 16666666; // 60 times a second (nanosecs)
int updates;
int max_updates = 5;
int draws = 0;
update_next = steady_clock::now();

while (true)
{
updates = 0;
update_time = steady_clock::now();
while (duration_cast<nanoseconds>(update_time - update_next) > nanoseconds(update_rate) && updates++ < max_updates)
{
if (draws <= 1) {
cout << "!!!!!!!!!!!!!ERROR!!!!!!!!!!!!!" << endl;
}
cout << "UPDATE - ";
cout << "Draws: " << draws
<< " - UT - UN: " << duration_cast<nanoseconds>(update_time - update_next).count()
<< endl;

draws = 0;
update_next += nanoseconds(update_rate);
}
draws++;
Draw();
}

return 0;
}
  • 也许我对典型应用程序有一些不了解的地方? Windows 是否需要经常劫持 CPU 周期?
  • 我在 steady_clock、clock 和充实的 SFML 应用程序中看到过这个问题,该应用程序的工作是在更新和绘制期间完成的
  • 我假设 SFML 时钟可能使用 time.h 时钟
  • 根据我的测试,max_updates 检查与此问题无关(我认为它们不会导致问题)

事实上,我在几个不同的计时器上看到过这种情况,这让我相信我的实现或我的系统有问题。这个例子是在 VS 中运行的,但我也在独立版本的 exe 中看到过它。玩弄更新率或绘制中完成的工作量可能会帮助它显示给你。


在测试了我的后台进程之后,我注意到了一个奇怪的相关性。此跳过问题仅在 Spotify 网络播放器在 Chrome 中打开时出现,并且大约每秒出现一次。

我找到了这篇可能相关的帖子: https://community.spotify.com/t5/Other-Partners-Web-Player-etc/Web-Player-on-Chrome-causes-lag-stutter/td-p/4587103

最佳答案

Perhaps there is something I don't understand about typical applications? Does Windows need to hijack CPU cycles every so often?

是的,绝对是。 Windows 正在同时运行大量进程。现在您的应用程序出现并执行本质上是一个繁忙的自旋循环。在某些时候,操作系统可能会降低其优先级的时间比您预期的要长,因为它看起来像是一个漫长的计算,并且操作系统需要为其他进程提供公平份额的 CPU 时间。

一般来说,您不应该依赖每秒调用精确次数的绘图例程,并且您的游戏的主时钟应该能够处理跳帧。我不熟悉 SFML,所以我不能对此发表评论。

但是,我确实有过在每秒超过 1000 次更新的循环中运行实时音频(以及与此相关的视频)的经验。您可以通过将线程优先级设置为 THREAD_PRIORITY_HIGHEST 或 THREAD_PRIORITY_TIME_CRITICAL 来改善游戏循环时间份额(参见 SetThreadPriority)。

要使其有效,您还应该是一个行为良好的应用程序并定期执行某种等待。等待允许 OS 进行必要的任务切换以服务其他进程(其中几个也将是高优先级,并且通常高于您作为用户空间应用程序能够强制执行的级别)。

等待的明显位置是在您的下一个抽奖周期之前。与其以 100% 的核心利用率启动计时器,不如简单地计算您准备等待的时间并调用 std::this_thread::sleep_for .请记住,唯一的保证是 sleep 至少您指定的时间。它绝对可以而且将不止于此。但我建议您从这里开始并做一些实验。

关于c++ - Steady_Clock 在主游戏循环的更新之间跳过,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53735418/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com