基于OpenTK的游戏间歇性卡顿

3

我目前正在开发一款游戏,使用OpenTK进行渲染;C#,.Net 4.0,OpenGL 2。

在1280x1024分辨率的最大化窗口下,平均帧率约为400 FPS。在1680x1050分辨率下,平均帧率约为315 FPS。尽管帧率很高,但我仍然遇到间歇性的卡顿问题。

基本上,在约3秒钟的时间内,渲染会明显地卡顿,然后在约0.5到1秒钟内完全平滑。这个循环会一直重复。

根据卡顿情况,我的FPS计数器中没有显示出帧率下降。我通过计算帧数直到达到所需的更新频率,然后使用每秒钟的滴答数、更新频率的滴答数和计数的帧数来计算帧速率。使用这种方法,我只能在每半秒钟看到一次更新,但我从未见过帧率远低于我预期的水平。

如果将游戏窗口拖动到我的第二个显示器上,则问题会显著恶化。

在发布版本中运行应用程序并没有解决问题。

我使用了Redgate的ANTS对应用程序进行了性能分析。这指出了一些问题,我已经解决了。

这里有什么建议吗?


1
我的水晶球显示...它是在main.cs文件的第602行。 - Blindy
你能进一步描述“可见的卡顿”行为吗?你正在使用双缓冲吗? - holtavolt
在卡顿周期内,屏幕上的任何移动物体似乎会停留一段难以理解的时间,然后跳到本应该在“暂停”发生之前的位置。这种情况发生得非常迅速,几乎不可察觉,但足以让人感到烦恼。它看起来并不流畅。我正在使用双缓冲。 - Kelsie
1
我猜想我曾希望有人(也许是你?)能够建议在分析器中具体查找什么。目前我在分析器中唯一可疑的事情是每秒分配量会每秒钟突然增加,但这似乎与我看到的3秒卡顿周期不太吻合。 - Kelsie
你能尽可能地简化你的项目(同时仍然存在所描述的问题),并将其提供下载吗? - Eduard Wirch
显示剩余2条评论
1个回答

3
这种卡顿通常是由垃圾回收器引起的。监测您的收集计数并检查它们是否对应于卡顿期间(使用0、1和2作为参数调用GC.CollectionCount())。如果确实是这个原因,您需要进行性能分析并减少内存分配(对象池可以在这里提供帮助,使用短生命周期的类来替换结构体也可以)。一般来说,在正常游戏过程中不希望出现任何gen-1或gen-2的收集。
另外,确保两个显示器同步到相同的刷新率。即使是轻微的差异也会在从主显示器拖动窗口到辅助显示器时产生卡顿(我看到过60Hz和59.9Hz之间的差异会导致这种情况发生)。编辑:禁用软帧速率限制器(例如调用Run()或Run(60),但不是Run(60, 60))并启用垂直同步。这可能有助于减少卡顿。

谢谢这里的提示,我会查看垃圾回收相关内容并看看我能得出什么。我没有使用内置的OpenTK消息泵,所以Run(..., ...)不适用。相反,我有一个专门的线程用于渲染循环,并使用标准的Application.Run消息泵来处理Form。我在渲染线程中创建了GraphicsContext,而不是使用OpenTK GLControl或GameWindow。我也会尝试使用VSync。 - Kelsie
刷新率建议看起来非常有前途。我的主屏幕的刷新率可以设置为50或60 Hz。我的次要屏幕的刷新率可以设置为60、70和75 Hz。如果两个屏幕都像以前一样设置为60,那么卡顿会间歇性地出现,就像描述的那样。如果任何一个屏幕的刷新率改变了,问题几乎是恒定的,也许在10-20秒的时间内会平稳地持续一瞬间。有没有办法真正解决这个问题?我可能会开一个新的问题,提供这些具体信息,并接受你在这里的答案。 - Kelsie
视频驱动程序总是同步于第一台显示器的刷新率。这个卡顿现象在第一台显示器、第二台显示器还是两者都有? - The Fiddler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接