停止播放器时,如何阻止播放器因本地输入预测而漂移?


14

我正在开发2D服务器-客户端多人游戏引擎(您可以在此处尝试)。它使用WebRTC DataChannel。(连接是对等的,但主机对等方仍充当服务器。)

除了连接性之外,最大的问题是本地输入预测。我们照常做:在按键时,玩家立即移动,告诉主机按下了哪些键,从主机接收回数据并将其与历史位置进行比较。如果存在差异,则随时间校正位置。即使ping高,这在低丢包率或PDV情况下也能很好地工作。

如果存在损耗或PDV,则偏差可能会更大。我认为这是因为,如果第一个指示输入变化的数据包被延迟或丢弃,主机将稍后发现,并在其本地输入条件显示之前开始更改该玩家。

如果玩家正在移动,我们会提高校正的幅度,因为它不太明显。这似乎弥补了开始移动和移动时的空白。但是,如果它们突然停止,则更明显。然后,如果PDV或丢失表示主机认为主机稍后停止,则主机超调,发送回数据,表示主机距离主机稍远,而校正会使播放器稍微偏离一点。在不稳定的连接中,玩家通常在停下来后通常会漂移。

我没有在其他游戏中注意到这一点。如何缓解这种情况?


3
有服务器的P2P游戏?这里有问题。
API-Beast

糟糕,“服务器”是指“主机对等方”。
AshleysBrain 2014年

2
好吧,这看起来也不像是点对点模型,只是因为其中一个参与者冒充了服务器而不是点对点模型。您所采用的技术绝对是客户端-服务器技术。在P2P中,您要么完全信任所有客户端(例如,每个对等方问对方,他们的玩家在哪里),要么不信任任何客户端(例如,您延迟输入,直到所有对等方都收到了)。
API-Beast

嗯...实际上这是个好点...我很困惑:连接是点对点的(这是WebRTC所做​​的),但是引擎本身是服务器-客户端(对等项之一就是服务器) )。好点子。
AshleysBrain 2014年

2
这让我想到的是我们自己在YouTube上的Andrew RussellStick Ninjas开发日志,尤其是关于修复预测错误的日志。您所描述的漂流听起来与该视频中发生的事情非常相似,而Andrew讲述了细节。这些是否相关,或者甚至是相同的问题?
Anko 2014年

Answers:


8

网络层需要有一个约定的时钟。他们可以在游戏初期就商定一个时钟值(并在漂移的情况下定期重新同步),以便主机知道任何特定数据包实际到达需要多长时间以及客户端何时进行操作,反之亦然。

有关使游戏中的时钟同步的一种可能方式,请参阅本文。还有其他 具体方法无关紧要。

问题的后半部分是服务器在客户端停止施加输入之后超过了施加输入的时间。这需要缓冲服务器上过去的运动,以及客户机上的某些逻辑,以忽略来自服务器的过去已知运动之后的运动输入。

首先,服务器缓冲区。服务器需要跟踪从播放器收到的最后一个输入的时钟标记。它还需要适用于玩家的所有机芯,即机芯的时标。如果接收到输入,则会丢弃所有比输入包更新的带有时钟标记的最近移动,并从输入包中重新应用所有移动。因此,如果服务器基于某些输入使玩家过度移动,则更新后的输入将抵消这些移动,并且玩家的新位置将基于服务器具有的最新输入知识。

在客户端,客户端知道上一次将输入发送到服务器的时间。由于服务器上的每个播放器更新都应标记有服务器知道的最后一次输入的时钟,因此客户端可以忽略具有过期输入标签的服务器更新,而只需遵循客户端的预测即可。最终,新服务器更新将以最新输入信息出现,客户端可以针对这些更新进行更正。

服务器需要验证输入时钟,并确保它们不会偏离期望值太多以防止作弊。输入时钟不应大大大于您应计算的半程往返时间。夹紧任何在合理范围内的物体([Now-2*RTT,Now]例如)。

如果延迟时间较长,客户端会看到很多其他玩家头像的抖动,因为他们会根据过时的输入从服务器获取更新,但无法知道服务器是否过时,然后服务器可能会根据发送的不同位置开始发送收到的更新后的输入(删除其历史记录的一部分,然后使用新的输入重播)。与其他玩家一起看到的最后一个问题确实无法解决您的头像抖动。延迟很糟糕,而滞留在高延迟连接上的游戏玩家会看到许多其他玩家的手足无措,即使他们自己的玩家动作平稳。唯一的校正是在更好的连接上或与具有较小延迟的对等/服务器一起玩。


1

我已经使用可靠的UDP消息来指示按钮状态更改,并使用了不可靠的UDP消息来进行位置校正。基本上,以下文章对我有很大帮助:https : //developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

它通过根据位置校正消息的到达以固定的时间间隔存储玩家状态来进行运动预测,以节省大约20或30个状态。因此,通过不断应用预测技术,看起来您的远程播放器实际上将生存在不太远的“过去”中:)基于净消息延迟,您可以在刚从主机发送消息时获得大约时间的对象位置。

然后可以使用Lerp(线性插值)数学将当前的“屏幕上”位置平滑地转换为预测位置。想法是在校正包之间的时间间隔内插值。因此,看起来显示的对象总是朝着某个预测位置移动。对于插值,我采用1除以“中等消息等待时间”除以“中等帧渲染时间”,因此运动看起来很平滑。

在这种情况下,游戏将在所有客户端上进行计算,并且服务器会不时地更正诸如速度和位置之类的值。

在这种情况下,还有很多其他帮助:优化游戏逻辑,确保服务器和客户端可以根据玩家的输入模仿相似的行为,从而轻松抵消延迟效应。

我已经描述了我在项目中使用的整个方案,所以希望您能找到问题的答案。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.