通过线程实现游戏引擎确定性

Vit*_*meo 3 c++ multithreading deterministic game-engine

我想在我的游戏引擎中实现确定性,以便能够保存和重放输入序列并使网络更容易.

我的引擎目前使用一个可变的时间步长:每一帧我计算更新/绘制最后一个时间并将其传递给我的实体的更新方法所花费的时间.这使得1000FPS游戏看起来像30FPS游戏一样快,但引入了不确定行为.

一个解决方案可能是将游戏固定到60FPS,但它会使输入更加延迟,并且不会获得更高帧率的好处.

所以我尝试使用一个线程(不断调用update(1)然后休眠16ms)并在游戏循环中尽可能快地绘制.它有点工作,但它经常崩溃,我的游戏变得无法播放.

有没有办法在我的游戏循环中实现线程来实现确定性而不必重写所有依赖于引擎的游戏?

小智 5

您应该将游戏帧与图形框架分开.图形框架应该只显示图形,没有别的.对于重放,无论您的计算机能够执行多少图形帧,无论是每秒30帧还是每秒1000帧,重放计算机都可能以不同的图形帧速率重放它.

但你应该确实修复游戏框架.例如,每秒100个游戏帧.在游戏框架中,游戏逻辑被执行:与游戏相关的东西(以及重放).

只要没有必要的游戏框架,你的游戏循环应该执行图形框架,所以如果你将游戏修改为每秒100个游戏帧,那么每个游戏帧只需0.01秒.如果您的计算机在游戏框架中只需要0.001来执行该逻辑,则剩下的其他0.009秒用于重复图形框架.

这是一个很小但不完整但不是100%准确的例子:

uint16_t const GAME_FRAMERATE = 100;
uint16_t const SKIP_TICKS = 1000 / GAME_FRAMERATE;

uint16_t next_game_tick;

Timer sinceLoopStarted = Timer(); // Millisecond timer starting at 0
unsigned long next_game_tick = sinceLoopStarted.getMilliseconds();

while (gameIsRunning)
{
    //! Game Frames
    while (sinceLoopStarted.getMilliseconds() > next_game_tick)
    {
        executeGamelogic();

        next_game_tick += SKIP_TICKS;
    }

    //! Graphical Frames
    render();
}
Run Code Online (Sandbox Code Playgroud)

以下链接包含有关创建精确游戏循环的非常完整的信息:

http://www.koonsolo.com/news/dewitters-gameloop/