12

我正在 XNA 中尝试使用lidgren,但我遇到了一些“滞后”问题。

我已经下载了他们的XNA 样本,并注意到他们的样本甚至滞后。问题是,另一边的运动并不顺畅,我正在局域网(实际上是在同一台计算机上)而不是通过互联网尝试这个。

由于与 lidgren 和 XNA 的连接滞后,是否有任何关于运动不顺畅的问题?

4

2 回答 2

38

您链接的样本直接将位置设置为从网络接收到的任何内容,这对于多人游戏来说是个坏主意!

在真实游戏中你应该做的是在本地位置和远程位置之间进行插值。所以,你的接收方法看起来有点像这样:

void Receive(packet)
{
    unit.RemoteX = packet.Read_X_Position();
    unit.RemoteY = packet.Read_Y_Position();
}

这对单元上的本地位置没有影响,而是在您的更新方法(每一帧)中,您将本地位置移向远程位置:

void Interpolate(deltaTime)
{
    difference = unit.RemoteX - unit.LocalX
    if (Math.Abs(difference) < threshold)
        unit.LocalX = unit.RemoteX
    else
        unit.LocalX += difference * deltaTime * interpolation_constant
}

然后显示单元的“本地”位置,这样可以实现无滞后运动,如下所示:

  1. 如果单元位置几乎在远程位置,它会跳到远程位置(但是,它会跳一个很小的距离,看起来不会滞后)。
  2. 如果差异太大而无法跳跃,则缓慢地向您应该处于的位置移动。

由于该单元平稳地向应在的位置移动,因此看起来完全没有滞后!

插值常数控制本地和远程位置收敛的速度:

  • 0:忽略网络更新
  • 小:快速卡入到位(可能看起来迟钝)
  • 大:慢慢滑入到位,看起来很光滑,但可能感觉没有反应

您需要在这些选项之间选择一个折衷方案。

在实现这种系统时,还有一些其他的事情需要考虑,例如,您通常希望对单元与其远程位置之间的距离设置一个上限,否则在某些情况下本地和远程状态可能会变得“不稳定”。如果它们相距太远(除非极度滞后,否则永远不会发生这种情况),您可以停止游戏并告诉用户它太滞后,或者将单元直接跳到位置,这看起来很滞后,但至少游戏会继续。

附录:重读这个答案,我想到一个改进是跟踪时差。如果您(大致)知道系统中的延迟是什么,那么您就知道当您收到一个远程位置的数据包时,您大致知道该数据包距离过去多远。如果您也发送远程速度,您可以预测对象现在的位置(假设速度恒定)。在某些游戏中,这可能会使估计的本地状态和真实远程状态之间的差异更小,而在其他游戏(您有很多变化的速度)中,它可能会使事情变得更糟。

于 2010-07-18T19:52:25.320 回答
1

我一直在考虑编写一个多人 fps 游戏,从一个演示开始,该演示只是移动一些立方体并在另一台处于旁观模式的机器上复制位置/旋转。

我正在使用您上面的代码示例,它运行良好(我不得不将插值常数调整为高于 1 以使其看起来平滑)。

我看过一些插值示例,它们考虑了当前时间与接收到的消息上的时间戳之间的时间差。

我看到这段代码不使用时间差,因此插值将需要尽可能长的时间才能达到目标值(或至少在阈值内然后卡入位置)。我的问题是,这样做有什么好处吗?

非常感谢。

于 2011-02-11T14:40:12.347 回答