简体   繁体   中英

How to implement precise game loop frame limiting in C#?

I'm attempting to implement a game loop frame limiter in a game engine written in C#. I was told Thread.Sleep requires a few milliseconds to even execute Thread.Sleep(0) , and would miss the target milliseconds a bit. It is thus not precise enough for what I need, because the target frame rate can require the engine to sit and wait for 1 millisecond. I'm not sure I should be using Thread.SpinWait in this, as there can also be situations where the engine needs to wait for 10 milliseconds, and I don't know if in such a situation it's a bad idea to use SpinWait.

Here's a snippet of code to illustrate what I'm trying to achieve:

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
    }
}

See now this is where you need to do the tests yourself to see what is actually happening, not just take someone at their word.

Running 1000000 passes through a loop to measure the time taken by Thread.Sleep(0) I get an average of 2.44 microseconds per execution, with minimum at 1.70 microseconds and maximum of 6.49 milliseconds. While that last figure sounds like a problem it actually isn't. Of the million passes only 59 of them (that's 0.0059%) were 1ms or more.

The point of calling Thread.Sleep(0) is to release the rest of your timeslice back to the system for other processes to use. It stops your process from hogging all of the available CPU time when it doesn't need to.

What it isn't is particularly accurate, because it's at the mercy of the task scheduler. But then, just about everything in the system is. Short of running at Real Time priority on one or more cores you won't get much better accuracy.

You can use a hybrid solution where you call Thread.Sleep(0) when the time to wait is more than a couple of milliseconds, then does a busy loop while it waits for a Stopwatch or similar to tick over the last few microseconds. Depends on how time-sensitive your code is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM