在尝试在SFML中制定稳定的游戏循环的过程中,我遇到了一个问题,似乎无法解决。我能够剥离所有SFML代码,并仍然通过time.h中的
问题是: 有时候,在更新之间可以完成的工作量会出现跳跃。每次更新应该花费1/60秒的时间,其余时间用于
clock()
看到这个问题。接着我更深入地去尝试,使用std::chrono::steady_clock
仍然能看到问题。问题是: 有时候,在更新之间可以完成的工作量会出现跳跃。每次更新应该花费1/60秒的时间,其余时间用于
Draw()
以尽可能多地进行绘制。
有时绘制量会降至0或1,原因不明。除了这些“跳跃”外,完成的绘制数量非常一致。
以下是一张图片(请注意更新时间的跳跃和绘制量的下降):
问题的控制台输出
一些代码:#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应用程序中看到了这个问题,在Update和Draw期间进行了一些工作
- 我认为SFML时钟可能使用time.h clock
- 根据我的测试,max_updates检查与此问题无关(我认为它们不会引起问题)
我看到几个不同的计时器都出现了这个问题,这让我相信我的实现或系统存在问题。该示例在VS中运行,但我也在独立的发布exe中看到过。尝试调整更新速率或绘制中完成的工作量可能会帮助您发现它。
在测试完我的后台进程后,我发现了一个奇怪的相关性。只有在Chrome中打开Spotify网络播放器并且大约每秒钟发生一次才会出现这个跳跃问题。
我找到了这篇文章,可能与此相关: https://community.spotify.com/t5/Other-Partners-Web-Player-etc/Web-Player-on-Chrome-causes-lag-stutter/td-p/4587103
std::this_thread::yield
有多有效?编辑:也就是说,在调用std:this_thread::yield
时旋转是否是减少过度睡眠可能性的有效方法。 - James Piconesleep_for
可能会延迟,因此您可以使用比实际需要更短的睡眠时间,然后使用yield
进行更紧密的自旋“睡眠”,以填补任何不足之处。这取决于实验和黑魔法。 - paddy