【问题标题】:Is event recording on time-sensitive possible?时间敏感的事件记录可能吗?
【发布时间】:2011-06-06 01:44:22
【问题描述】:

基本问题

有没有办法在时间敏感(与帧率无关)系统中记录回放?

任何帮助 - 包括简单的“抱歉,这是不可能的” - 将不胜感激。在过去的几个周末里,我花了将近 20 个小时来解决这个问题,我快把自己逼疯了。

详细信息

这是目前针对游戏的,但我正在编写的库被设计为更通用,这个概念不仅仅适用于我的 C++ 编码。

我有一些看起来功能相似的代码......(它是用 C++0x 编写的,但我冒昧地让它更紧凑)

void InputThread()
{
    InputAxisReturn AxisState[IA_SIZE];
    while (Continue)
    {
        Threading()->EventWait(InputEvent);
        Threading()->EventReset(InputEvent);

        pInput->GetChangedAxis(AxisState);

        //REF ALPHA

        if (AxisState[IA_GAMEPAD_0_X].Changed)
        {
             X_Axis = AxisState[IA_GAMEPAD_0_X].Value;
        }
    }
}

我有一个单独的线程,看起来像这样......

//REF BETA
while (Continue) 
{
    //Is there a message to process? 
    StandardWindowsPeekMessageProcessing();

    //GetElapsedTime() returns a float of time in seconds since its last call
    UpdateAll(LoopTimer.GetElapsedTime());
}

现在我想记录输入事件以进行回放测试和一些有限的回放功能。

只需在我标记为 //REF ALPHA 的位置插入以下代码,我就可以轻松地以精确的时间记录事件

//REF ALPHA
EventRecordings.pushback(EventRecording(TimeSinceRecordingBegan, AxisState));

真正的问题是回放这些。我的 LoopTimer 使用高性能计数器 (QueryPreformanceCounter) 具有极高的精度。这意味着使用如下代码代替 //REF BETA

几乎不可能达到相同的时差
// REF BETA
NextEvent = EventRecordings.pop_back()
Time TimeSincePlaybackBegan;
while (Continue) 
{
    //Is there a message to process? 
    StandardWindowsPeekMessageProcessing();

    //Did we reach the next event?
    if (TimeSincePlaybackBegan >= NextEvent.TimeSinceRecordingBegan)
    {
        if (NextEvent.AxisState[IA_GAMEPAD_0_X].Changed)
        {
             X_Axis = NextEvent.AxisState[IA_GAMEPAD_0_X].Value;
        }

        NextEvent = EventRecordings.pop_back();
    }

    //GetElapsedTime() returns a float of time in seconds since its last call
    Time elapsed = LoopTimer.GetElapsedTime()
    UpdateAll(elapsed);
    TimeSincePlabackBegan += elapsed;
}

这种方法的问题在于,您几乎永远不会在完全相同的时间播放,因此您将有几微秒的时间播放与录音不匹配。

我也尝试过事件捕捉。一种令人困惑的术语,但基本上如果 TimeSincePlaybackBegan > NextEvent.TimeSinceRecordingBegan 然后 TimeSincePlaybackBegan = NextEvent.TimeSinceRecordingBegan 和 ElapsedTime 被改变以适应。

它有一些你可以预料到的有趣的副作用(比如一些减速),但不幸的是它仍然导致播放不同步。

了解更多背景信息 - 这可能是我的时间捕捉方法不起作用的原因 - 我在 UpdateAll 调用的某个地方使用了 BulletPhysics。有点像……

void Update(float diff)
{
    static const float m_FixedTimeStep = 0.005f;
    static const uint32 MaxSteps = 200;

    //Updates the fps
    cWorldInternal::Update(diff);

    if (diff > MaxSteps * m_FixedTimeStep)
    {
        Warning("cBulletWorld::Update() diff > MaxTimestep. Determinism will be lost");
    }

    pBulletWorld->stepSimulation(diff, MaxSteps, m_FixedTimeStep);
}

但我也尝试使用 pBulletWorkd->stepSimulation(diff, 0, 0) ,根据http://www.bulletphysics.org/mediawiki-1.5.8/index.php/Stepping_the_World 应该可以解决问题,但仍然无济于事。

【问题讨论】:

    标签: c++ events playback deterministic


    【解决方案1】:

    为遇到此问题的其他人回答我自己的问题。

    基本上,如果您想要确定性的录制和播放,您需要锁定帧速率。如果系统无法处理帧速率,则必须引入减速或风险不同步。

    经过两周的额外研究,我认为这是不可能的,因为浮点数不足以及浮点数不一定具有关联性。

    拥有依赖浮点数的确定性引擎的唯一解决方案是拥有稳定且固定的帧速率。从长远来看,帧速率的任何变化都会导致播放不同步。

    【讨论】:

      猜你喜欢
      • 2019-12-16
      • 1970-01-01
      • 1970-01-01
      • 2016-02-13
      • 2020-04-03
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      • 1970-01-01
      相关资源
      最近更新 更多