简体   繁体   English

游戏时间越快,帧率越慢,不同帧率的增量时间不一致

[英]Game time speeds up the slower the frame rate, delta time inconsistent across different framerates

Here is how I am calculating the delta time:这是我计算增量时间的方法:

currentTime = std::chrono::high_resolution_clock::now();
deltaTime = std::chrono::duration<float, std::chrono::seconds::period>(currentTime - lastCurrentTime).count();
lastCurrentTime = currentTime;

From the very beginning of this project I noticed the delta time did not give me consistent results across different frame rates.从这个项目的一开始,我就注意到增量时间并没有给我在不同帧速率下的一致结果。 Everything that uses this deltaTime speeds up the slower the framerate is, but as an example, here is how the camera moves forward:使用此 deltaTime 的所有东西都会加快帧速率的速度,但作为示例,这是相机向前移动的方式:

playerPosition += playerForward * speed * deltaTime;

I could show you the entire main loop, but that shouldn't matter, however long it takes should be accounted for.我可以向您展示整个主循环,但这无关紧要,无论需要多长时间都应该考虑在内。 I remember one time I had a problem with std::chrono and it was because the compiler "optimized" the start timer to a completely different place.我记得有一次我遇到了 std::chrono 的问题,那是因为编译器将启动计时器“优化”到了一个完全不同的地方。 Could that be happening here?这会发生在这里吗? And if so, is there a better way of calculating delta time in C++?如果是这样,是否有更好的方法来计算 C++ 中的增量时间?

Don't use std::chrono::high_resolution_clock , it is implementation-defined.不要使用std::chrono::high_resolution_clock ,它是实现定义的。 Stick to std::chrono::steady_clock instead.而是坚持使用std::chrono::steady_clock Additionally, your problem is here: std::chrono::duration<float, std::chrono::seconds::period>(currentTime - lastCurrentTime).count();此外,您的问题在这里: std::chrono::duration<float, std::chrono::seconds::period>(currentTime - lastCurrentTime).count(); . . You are defining the period as a variable-length instead of a constant length which will cause your deltaTime to change "length" between calls.您将周期定义为可变长度而不是恒定长度,这将导致您的 deltaTime 在调用之间更改“长度”。

You can simplify your problem by defining a using for a float-based seconds:您可以通过为基于浮点数的秒数定义一个 using 来简化您的问题:


namespace TimeUtils {

using FPSeconds = std::chrono::duration<float>;
using FPMilliseconds = std::chrono::duration<float, std::milli>;
using FPMicroseconds = std::chrono::duration<float, std::micro>;
using FPNanoseconds = std::chrono::duration<float, std::nano>;
using FPFrames = std::chrono::duration<float, std::ratio<1, 60>>;
using Frames = std::chrono::duration<uint64_t, std::ratio<1, 60>>;


template<typename Clock = std::chrono::steady_clock>
[[nodiscard]] decltype(auto) Now() noexcept {
    return Clock::now();
}

std::chrono::nanoseconds GetCurrentTimeElapsed() noexcept {
    static auto initial_now = Now<std::chrono::steady_clock>();
    auto now = Now<std::chrono::steady_clock>();
    return (now - initial_now);
}

//...
} //end TimeUtils

static TimeUtils::FPSeconds previousFrameTime = TimeUtils::GetCurrentTimeElapsed();
TimeUtils::FPSeconds currentFrameTime = TimeUtils::GetCurrentTimeElapsed();
TimeUtils::FPSeconds deltaSeconds = (currentFrameTime - previousFrameTime);
previousFrameTime = currentFrameTime;

//...Prevents death-spiral when stepping through debugger
#ifdef DEBUG_BUILD
    deltaSeconds = (std::min)(TimeUtils::FPSeconds{TimeUtils::FPFrames{1}}, deltaSeconds);
#endif

//...

Update(deltaSeconds);

Now you can declare your deltaTime as TimeUtils::FPSeconds deltaTime in function arguments.现在您可以在函数参数中将deltaTime声明为TimeUtils::FPSeconds deltaTime This allows you to express it in any std::chrono::duration format you want as it will be converted automagically:这允许您以您想要的任何std::chrono::duration格式来表达它,因为它将自动转换:

void Foo(TimeUtils::FPSeconds deltaSeconds);

Foo(TimeUtils::FPMilliseconds{10.0f}); //Automatically converted to 0.010f seconds

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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