如何在c#中实现精确的游戏循环帧限制
本文关键字:游戏 循环 实现 | 更新日期: 2023-09-27 18:19:21
我正在尝试在c#编写的游戏引擎中实现游戏循环帧限制器。我被告知Thread.Sleep
甚至需要几毫秒来执行Thread.Sleep(0)
,并且会稍微错过目标毫秒。因此,它不够精确,因为目标帧率可能需要引擎等待1毫秒。我不确定我应该在这使用Thread.SpinWait
,因为也可能存在引擎需要等待10毫秒的情况,我不知道在这种情况下使用SpinWait是否是个坏主意。
这里有一段代码来说明我想要实现的目标:
public void Run()
{
var targetDelta = TimeSpan.FromSeconds(0.016);
Running = true;
while (Running)
{
// Calculate time since previous frame start here ("delta")
// Simplified, but essentially this is what's going on
Input.HandleEvents();
Scene.Update(delta);
Renderer.Render(Scene);
// Perform waiting to limit frame rate here
}
}
看,这就是你需要自己做测试的地方,看看实际发生了什么,而不仅仅是相信别人的话。
运行1000000通过一个循环来测量Thread.Sleep(0)
所花费的时间,我得到每次执行的平均时间为2.44微秒,最小为1.70微秒,最大为6.49毫秒。虽然最后一个数字听起来像是一个问题,但实际上并不是。在100万次传递中,只有59次(0.0059%)的传递时间在1毫秒以上。
调用Thread.Sleep(0)
的目的是将剩余的时间片释放回系统供其他进程使用。它可以防止进程在不需要的时候占用所有可用的CPU时间。
它不是特别准确,因为它受任务调度器的支配。但是,系统中的所有东西都是。如果没有在一个或多个核心上以实时优先级运行,您将无法获得更好的准确性。
您可以使用混合解决方案,当等待时间超过几毫秒时调用Thread.Sleep(0)
,然后在等待Stopwatch
或类似的时间在最后几微秒内滴答时执行忙循环。