处理 XNA + lidgren 中的延迟
Posted
技术标签:
【中文标题】处理 XNA + lidgren 中的延迟【英文标题】:Dealing with lag in XNA + lidgren 【发布时间】:2011-03-17 15:36:35 【问题描述】:我正在 XNA 中尝试使用 lidgren,但遇到了一些“滞后”问题。
我已经下载了他们的XNA sample 并注意到即使是他们的示例也有滞后。问题是,另一边的移动并不顺畅,我正在 LAN(实际上是在同一台计算机上)而不是通过 Internet 尝试此操作。
由于与 lidgren 和 XNA 的连接滞后,有没有人遇到过相同的运动不顺畅的问题?
【问题讨论】:
这个问题似乎跑题了,应该移到 Gamedev.SE gamedevSE 在 2010 年发布时是否活跃? 【参考方案1】:您链接的示例直接将位置设置为从网络接收到的任何内容,这对于多人游戏来说是个坏主意!
您在真实游戏中应该做的是在本地位置和远程位置之间进行插值。所以,你的接收方法看起来有点像这样:
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
然后显示单元的“本地”位置,这样就可以实现无延迟移动,如下所示:
-
如果单元位置几乎在远程位置,它会跳到远程位置(但是,它会跳的距离很小,不会显得迟钝)。
如果差异太大而无法跳跃,则缓慢地向应在的位置移动。
由于单位平稳地移动到它应该在的位置,看起来完全没有滞后!
插值常数控制本地和远程位置收敛的速度:
0:忽略网络更新 小:非常快速地卡入到位(可能看起来迟钝) 大:慢慢滑入到位,看起来很光滑,但可能感觉反应迟钝您需要在这些选项之间做出妥协。
在实施此类系统时,还需要考虑其他一些事项,例如,您通常希望对单元与其远程位置之间的距离设置一个上限,否则在某些情况下本地和远程状态可能会变得“不稳定” .如果它们相距太远(除非极度滞后,否则永远不会发生),您可以停止游戏并告诉用户它太滞后,或者直接将单元跳到位置,这看起来很滞后,但至少游戏会继续。
附录:重读这个答案,我想到一个改进是跟踪时差。如果您(大致)知道系统中的延迟是什么,那么您就知道当您收到一个远程位置的数据包时,您大致知道该数据包距离过去多远。如果您也发送远程速度,您可以预测对象现在的位置(假设速度恒定)。在某些游戏中,这可能会使估计的本地状态和真实远程状态之间的差异更小,而在其他游戏中(您有很多变化的速度),这可能会使事情变得更糟。
【讨论】:
相信我,我会接受这个答案 :-) 我也非常感谢您的电子邮件合作。 @NiCkNewman 阈值是当两件事如此接近时,您可以在没有任何人注意到的情况下捕捉到网络位置。如果你的插值系统足够好,它基本上可以设置为你喜欢的任意低。 这可能是两件事之一。要么:1)您需要稍微调整一下插值常数,或者 2)这种方法从根本上是有限的,您需要实现我在附录中添加的内容。基本上,您发送运动矢量并预测玩家将如何移动,因此您可以对远程状态进行更准确的本地插值。 我不同意“用常数 1 它会直接传送到网络位置” 很好的答案!不过,它应该是 if 条件中的 Math.abs(difference)。【参考方案2】:我一直在考虑编写一个多人 fps 游戏,从一个演示开始,该演示只是移动一些立方体并在另一台处于旁观模式的机器上复制位置/旋转。
我正在使用您上面的代码示例,它运行良好(我不得不将插值常数调整为高于 1 以使其看起来平滑)。
我见过一些插值示例,它们考虑了当前时间和接收到的消息上的时间戳之间的时间差。
我看到此代码不使用时间差,因此插值将需要尽可能长的时间才能到达目标值(或至少在阈值内然后卡入位置)。我的问题是,这样做有什么好处吗?
非常感谢。
【讨论】:
以上是关于处理 XNA + lidgren 中的延迟的主要内容,如果未能解决你的问题,请参考以下文章