这是一个旧问题,但我最近已经编写了类似的代码,所以也许这会帮助到某些人。
是的,延迟在计算中总是有用的。 但它比RTT略微复杂。 回程时间始终在变化...你的网络代码可以保持平均值,但与该平均值的方差很大。
本地客户端、远程客户端和服务器都使用算法预测当前位置。以下数据接近典型:
- 时间:t
- 位置:位置(x,y,z)和方向(x,y,z,w)
- 移动:线性运动矢量给出方向,长度为速度(x,y,z),和旋转运动矢量给出轴,长度为旋转速度(x,y,z)
您需要算法,从[T,P,M]集合推导出simtime。我不会在这里提供那些。
当客户端在[T,P,M]上注册船只驾驶变化时,该变化直到T+deltaT才能到达服务器。但是,如果deltaT在典型网络延迟的公差范围内,则服务器可以说:“是的,它发生在T,我接受了。”否则,它可能想要纠正客户端,说“不,这超出了公差范围,它发生在我的时间T'”,此时客户端将不得不从服务器的纠正后的变化[T,P,M]开始重新播放(这意味着您需要保留它们的队列或列表)。
下一个客户端将在T+deltaT+differentdeltaT时获得它。它不可能改变已经模拟过的内容,因此,如果它没有延迟其模拟,它将跳过远程船只,您将看到一个抖动帧。这就是为什么远程驱动的船只应该将其模拟延迟一段时间,这段时间始终大于2 * typicaldeltaT。它应该是一个恒定的延迟,或者一个逐渐变化的延迟,在严重滞后的情况下,你仍会看到抖动帧
您可以使用额外的平滑代码来平滑所有抖动,但除非您的代码完美无缺,否则不要这样做,因为它只会使问题难以找到。
您必须拥有良好的同步时间参考。很多代码都处理得相当粗糙(例如RakNet并没有很好地处理它)。以下是一个好提示:在短期内,您可以假定每个人的时钟都以相同的速度运行,您只需要弄清楚偏移量是多少,因此保持最大和最小偏移量的窗口,并随着学习而关闭;从长远来看,您需要补偿那些时钟运行快或慢的客户端,因此如果确定必须这样做,则允许窗口打开。您必须使用本地时间源,它单调递增且不依赖于处理器速度(现在是可变的)。
不要延迟本地模拟当本地“avatar”移动。这看起来太不响应了。您可以稍微延迟一下(最多50毫秒)以帮助改善同步,但将延迟全部延伸到RTT会使您的游戏看起来令人沮丧地不响应。设置一个本地延迟选项并进行测试,因为小的一致延迟是可以接受的并且可以提高同步性能。但是这不是必要的,而且可能会导致很多问题,所以我建议在最后才编写此代码。(如果您正在尝试制作FPS格斗游戏,则需要执行此操作以及其他所有可用的帮助)。
至于防作弊与模拟平滑度:首先,当官方位置发生更改时,客户端不应只从上次已知位置进行外推。它应该注册一个调整向量并缓慢移动从旧路径到新路径以获得平滑度(但是如上所述,最后编写此代码,否则它将掩盖其他错误)。其次,服务器应容忍广泛的延迟...即使在同一以太网上的机器上,数据包延迟通常也会运行5ms至100ms左右...这是相当大的范围。当然,您需要切断它并说“如果您在时间T移动但我在T + some_large_number收到数据包,那么我认为您正在调整过去并向我撒谎。”some_large_number不应比平均RTT大得多,以保持人们的诚实。
模拟永远不会被紧密同步。它们应该在互联网上保持在400ms左右,但在延迟时肯定会偏离...到30秒或更长时间,并且您需要容忍这些事情,因为它们并不罕见。鉴于互联网受铜中光速的限制,您可以始终期望单向延迟通常至少在100ms最小值以上,通常为500ms或更长时间。
因此,我强烈建议您不要尝试在互联网上制作格斗FPS游戏(一些大公司尝试了但总是会遇到问题)。如果您使用投射物,则可以使用技巧(通过在一个模拟中快速运行它们,在另一个模拟中运行它们缓慢),使得即使时间不准确,看起来也是正确的。此外,FPS游戏使用命中检测基于攻击者的模拟...当攻击者知道他已经准确地瞄准却错过了时,感觉更加错误,而不是防守者知道他已经离开了位置,但仍然被击中。您必须选择其中之一,从心理学的角度来看,就是这样做的。格斗需要一种同步水平,这实际上是不可能的,大多数游戏公司不会涉足MMORPG FPS格斗游戏,而是使用自动瞄准(尝试玩玩《Mortal Online》,您会明白我的意思)。
祝你好运。