非射击者的运动预测


35

我正在开发具有中等规模的多人游戏的等距2D游戏,大约有20-30个玩家同时连接到持久性服务器。在实现良好的运动预测实现方面,我遇到了一些困难。

物理/运动

游戏没有真正的物理实现,但是使用基本原理来实现运动。状态更改(即/鼠标下移/上移/移动事件)不是持续轮询输入,而是用于更改玩家正在控制的角色实体的状态。玩家的方向(即东北方向)与恒定速度结合在一起,并转换为真实的3D矢量-实体的速度。

在主游戏循环中,在“平局”之前调用“更新”。更新逻辑触发“物理更新任务”,该任务以非常零的速度跟踪所有实体,并使用非常基本的积分来更改实体位置。例如:entity.Position + = entity.Velocity.Scale(ElapsedTime.Seconds)(其中“ Seconds”是浮点值,但相同的方法适用于毫秒整数值)。

关键是没有插值用于运动-基本物理引擎没有“先前状态”或“当前状态”的概念,只有位置和速度。

状态更改和更新数据包

当玩家控制的角色实体的速度发生变化时,“移动化身”数据包将发送到服务器,其中包含该实体的动作类型(站立,行走,奔跑),方向(东北)和当前位置。这与3D第一人称视角游戏的工作方式不同。在3D游戏中,速度(方向)会随着玩家的移动而逐帧变化。发送每个状态更改将有效地每帧发送一个数据包,这太昂贵了。取而代之的是3D游戏似乎忽略了状态更改,而是以固定的时间间隔(例如,每80-150毫秒)发送“状态更新”数据包。

由于速度和方向更新在我的游戏中的发生频率要低得多,因此我可以避免发送每个状态更改。尽管所有物理模拟都以相同的速度发生并且具有确定性,但是延迟仍然是一个问题。因此,我发出常规的位置更新数据包(类似于3D游戏),但发送频率却要低得多-现在每250毫秒发送一次,但是我怀疑有了良好的预测,我可以轻松地将其提高到500毫秒。最大的问题是,我现在已经偏离规范了-所有其他在线文档,指南和示例都会发送例行更新并在这两种状态之间进行插补。看来与我的架构不兼容,我需要提出一种更好的运动预测算法,该算法更接近(非常基本的)“网络物理学”架构。

然后,服务器接收该数据包,并根据脚本根据其移动类型确定玩家的速度(玩家是否可以跑步?获取玩家的跑步速度)。一旦具有速度,便将其与方向相结合以获得向量-实体的速度。会进行一些作弊检测和基本验证,并且服务器端的实体将使用当前速度,方向和位置进行更新。还执行基本限制,以防止玩家因移动请求而淹没服务器。

更新其自身的实体后,服务器向范围内的所有其他玩家广播“头像位置更新”包。位置更新包用于更新远程客户端的客户端物理模拟(世界状态),并执行预测和滞后补偿。

预测和滞后补偿

如上所述,客户具有自己的地位。除作弊或异常情况外,服务器将永远不会重新定位客户端的头像。客户的化身不需要进行推断(“立即移动并稍后更正”)-玩家看到的正确的。但是,所有正在移动的远程实体都需要某种类型的外推或内插。客户的本地模拟/物理引擎中显然需要某种类型的预测和/或滞后补偿。

问题

我一直在努力使用各种算法,并且遇到许多问题:

  1. 我应该外推,内插还是同时进行?我的“直觉”是我应该使用基于速度的纯外推法。客户端接收状态更改,客户端计算出补偿滞后的“预测”速度,而常规物理系统则完成其余工作。但是,它与所有其他示例代码和文章都不一样-它们似乎都存储了许多状态并在没有物理引擎的情况下执行插值。

  2. 当数据包到达时,我尝试在固定的时间段内(例如200ms)用数据包的速度对数据包的位置进行插值。然后,我利用插值位置和当前“错误”位置之间的差值来计算新矢量,并将其放置在实体上而不是发送的速度上。但是,假设另一个数据包将在该时间间隔内到达,并且很难猜测下一个数据包何时到达-尤其是因为它们并非都按固定的时间间隔到达(即,状态也发生变化)。这个概念从根本上是有缺陷的,还是正确的,但是需要一些修复/调整?

  3. 远程播放器停止播放时会发生什么?我可以立即停止该实体,但是它将定位在“错误”位置,直到再次移动为止。如果我估计一个矢量或尝试进行插值,则会遇到一个问题,因为我不存储先前的状态-物理引擎无法说“到达X位置后需要停止”。它只是了解速度,没有什么更复杂的了。我不愿意将“数据包移动状态”信息添加到实体或物理引擎,因为它违反了基本的设计原则,并在游戏引擎的其余部分流失了网络代码。

  4. 当实体碰撞时会发生什么?共有三种情况-控制玩家在本地发生冲突,两个实体在位置更新期间在服务器上发生冲突,或者远程实体更新在本地客户端上发生冲突。在所有情况下,我都不确定如何处理碰撞-除了作弊外,这两种状态都是“正确的”,但是处于不同的时间段。在远程实体的情况下,将其拖过墙是没有意义的,因此我在本地客户端上执行碰撞检测并使其“停止”。基于上面的第二点,我可能会计算出一个“校正向量”,该向量将不断尝试将实体“穿过墙”移动,但此操作将永远不会成功-远程化身被卡在那儿,直到错误变得过高并“捕捉”到位置。游戏如何解决这个问题?


1
3D或2D游戏与您使用哪种服务器有什么关系?以及为什么不为您的游戏工作的athantive服务器?
AttackingHobo

1
@Roy T.带宽权衡。带宽是当今计算机系统中最有价值的资源。
FxIII 2011年

1
这是不正确的,在线游戏主要由响应时间决定,例如,在10Mbit线路(1.25MB / s)上,服务器-客户端之间的延迟为20ms,发送1.25kb数据包将花费20ms + 1ms。发送12.5kb的数据包需要30毫秒。在两倍的快速线上,1.25kb的数据包仍将花费20ms + 0.5ms,而12.kb的数据包将花费20ms + 5ms。延迟是限制因素,而不是带宽。无论如何,我不知道有多少数据,但是发送50个vector3(25x位置+ 25x旋转)仅600字节,每20ms发送一次将花费30kb / s。(+数据包开销)。
罗伊T.11年

2
自第一个版本以来,Quake引擎就具有预测功能。这里和其他地方都描述了地震预报。看看这个。
user712092 2011年

1
您是否为每个实体并行地执行了position + = velocity * deltatime的操作(必须:在代码中,您有2个实体的物理参数数组,相距一帧,您将较旧的实体更新为较新的并交换它们)?Sean Barret的迭代存在一些问题,他是Thief 1发动机的基础
user712092 2011年

Answers:


3

唯一要说的是2D,等距,3D,当涉及到此问题时,它们都是相同的。因为您看到了许多3D实例,并且仅使用具有瞬时速度的2D八分位数限制输入系统,但这并不意味着您可以抛弃过去20多年发展而成的网络原理。

当游戏玩法受到损害时,该设计原则就该死!

通过扔掉以前和当前的内容,您将丢弃一些可以解决问题的信息。对于这些数据,我将添加时间戳和计算出的滞后,以便外推法可以更好地预测玩家的位置,并且内插法可以更好地消除速度随时间的变化。

以上是服务器似乎发出大量状态信息而不控制输入的重要原因。另一个重要原因是基于您使用的协议。UDP接收到丢包并无序发送?TCP可以保证交付和重试?使用任何协议,您都会在怪异的时间收到数据包,这些数据包会延迟或堆积在一系列活动中。所有这些奇怪的数据包都需要适合上下文,以便客户端可以了解正在发生的事情。

最后,即使您的输入仅限于8个方向,实际的更改也随时可能发生-强制执行250毫秒的周期只会令快速的玩家感到沮丧。30个玩家对任何服务器来说都不是什么大事。如果您正在谈论成千上万个...即使如此,它们的组也会分散在多个装箱中,因此各个服务器仅承担合理的负载。

您是否曾经描述过像Havok或Bullet running这样的物理引擎?它们确实非常优化,并且非常非常快。您可能会陷入陷阱,以为假设操作ABC会很慢,并且对不需要的操作进行了优化。


这里有一定的圣人建议!放宽全局很容易。在这种情况下,我正在使用TCP。就输入而言,“ 8向”问题已不再是一个大问题,而是内插和外推问题。图形仅限于这些角度,并使用动画小精灵-如果玩家以不同的角度或速度移动而超出正常水平,则游戏玩法“看起来很奇怪”。
ShadowChaser 2012年

1

因此,您的服务器本质上是“裁判”?在这种情况下,我认为您客户中的所有内容都必须具有确定性。您需要确保每个客户端上的所有内容始终会给出相同的结果。

对于第一个问题,一旦本地玩家获得了其他玩家的指导,除了能够随着时间的推移降低自己的运动并施加碰撞之外,我看不到如何预测玩家下一步的转向,尤其是在8方向环境。

当您收到每个玩家的“真实位置”更新时(也许您可以尝试在服务器上错开),是的,您将需要插值玩家的位置和方向。如果“猜测”位置非常错误(即,在发送最后一个方向数据包后玩家完全改变了方向),您将有很大的差距。这意味着玩家可以跳位,也可以插值到下一个猜测的位置。随着时间的推移,这将提供更平滑的插值。

当实体碰撞时,如果您可以创建确定性系统,则每个玩家都可以在本地模拟碰撞,并且它们的结果与现实之间的距离不应太远。每个本地计算机都应模拟两个玩家的碰撞,在这种情况下,请确保最终状态不会阻塞并且可以接受。

对于服务器方面,裁判服务器仍可以进行简单的计算,以检查例如短时间内运动员的速度,以用作简单的反作弊机制。如果您一次一次监视每个玩家一次,那么作弊检测将是可扩展的,找到作弊者只会花费更长的时间。


谢谢-听起来很接近我的需求,尤其是在服务器端。有趣的一点是,尽管玩家被锁定在8个方向上,但内部移动是3D向量。在过去的一天中,我对此进行了更多的思考,并且我在为自己根本没有实现插值而苦苦挣扎,我只是在使用一个非常基本的积分,即根据速度来设置速度并更新位置矢量每个更新。
ShadowChaser 2011年

我不确定如何将其与插值或预测结合使用。我尝试获取数据包中发送的更新位置,在固定时间段内(例如200ms)对其进行积分,然后确定在200ms内达到该点所需的向量(速度)。换句话说,无论玩家当前在客户端的错误位置如何,他们都应在200ms内达到相同的“估计正确位置”。最终,我的角色向疯狂的方向发送了出去-我想是因为200ms确实是到达下一个数据包的时间,我无法估计。
ShadowChaser 2011年

您是否确定先将tt + 1的正确位置积分,然后再将t + 1的错误位置积分到猜测的正确位置?
乔纳森·康内尔

是的-我再次检查了原始整合的正确位置。最初这是一个错误,但是修复它似乎并没有带来明显的改进。我的怀疑是“ +1”-它必须非常取决于数据包之间的时间。有两个问题:除了定期(250ms)更新外,还发送状态更改,我无法预测何时发生更改。另外,我也不愿意锁定一个特定的时间间隔,因为对于服务器而言,为远离玩家的实体发送较少的更新是有意义的。数据包之间的时间可以更改。
ShadowChaser

1
是的,包括固定的时间步长可能不是一个好主意。我担心尽管很难预测8向运动的不稳定性(如果不是不可能的话)。即使这样,您仍然可以尝试使用客户端的平均延迟来预测t + 1,并具有一个阈值,在该阈值之上,您始终会将其他玩家“传送”到他们的新位置。
乔纳森·康奈尔

0

您能否在状态更改消息中不包括速度并使用它来预测运动?例如,假设直到收到消息说速度发生变化,速度才保持不变?我认为您已经在发送职位,因此,如果因此而出现“过冲”,则无论如何您都具有下一次更新的正确职位。然后,您可以像使用上一条消息的速度那样在更新过程中步进位置,并在收到带有新位置的消息时覆盖位置。这也意味着,如果位置没有变化,但是速度需要您发送一条消息(如果这在您的游戏中甚至是有效的情况),但这不会对带宽使用造成太大影响。

插值在这里无关紧要,也就是说,例如,当您知道将来会有什么东西,是否拥有它,使用的是哪种方法等时,您是否会对推断感到困惑?(我所描述的是一种简单的方法)


-1

我的第一个问题是:使用具有服务器权限的模型有什么问题?环境是2D还是3D为什么很重要?如果您的服务器是权威的,它将使您的作弊保护变得更加容易。

我看到的大多数样本都将运动预测紧密地耦合到实体本身。例如,将先前状态与当前状态一起存储。我想避免这种情况,只将实体保持其“当前状态”。有没有更好的方法来解决这个问题?

执行预测时,有必要在客户端上维护几个状态(或至少是增量),以便当从服务器接收到权威状态/增量时,可以将其与客户端的状态/增量进行比较,从而可以进行必要的调整。更正。这个想法是保持尽可能确定性,以最大程度地减少所需的校正量。如果不维护以前的状态,则无法确定服务器上是否发生了其他变化。

玩家停下该怎么办?我无法内插到正确的位置,因为如果他们的位置太靠前,他们可能需要向后走或走另一个奇怪的方向。

为什么需要插值?权威服务器应覆盖任何错误的动作。

当实体碰撞时会发生什么?如果当前玩家与某物发生碰撞,答案很简单-停止玩家移动即可。但是,如果两个实体占用服务器上的相同空间会发生什么?如果本地预测导致某个远程实体与玩家或另一个实体发生碰撞该怎么办-我也应该停止它们吗?如果预测的不幸之处在于将其贴在玩家已经走过的墙前,则预测将永远无法进行补偿,一旦误差上升到高位,实体将捕捉到新位置。

在这些情况下,服务器和客户端之间会发生冲突,这就是为什么您需要维护客户端上的状态以便服务器可以更正任何错误的原因。

对不起,我很快就离开了。阅读这篇文章,它确实提到了射击游戏,但是应该适用于需要实时联网的任何游戏。


一些答案:*如果服务器具有权限,它将负责跟踪所有移动的实体并定期更新其位置。换句话说,它需要运行物理引擎-这可能会变得昂贵。可伸缩性是我的主要设计目标。*我需要在客户端进行插值,否则发送给客户端的每个服务器更新都会导致实体跳转。现在,我的插值是在物理引擎中完成的-它只是设置速度。没有状态或增量。
ShadowChaser 2011年

我已经阅读了格伦的所有文章,但他在评论中指出,它们仅适用于射击者(即更新频率高)。他的一些文章谈到了权威客户,这是我正在努力的实现。我不想在服务器上进行任何插值/物理操作,但是如果这确实是唯一的方法,我愿意改变主意:)
ShadowChaser

1
-1。您只写了些模糊的话题。感到am昧。当答案本质上是“阅读这篇较长的文章”,而又不包含来自本文的有用信息时,答案会低于标准。
AttackingHobo

1
@AttackingHobo我必须同意你的看法。我提到我很着急,但这不是借口。如果我没有时间,最好别管它。学过的知识。
吉安(Gyan)加里·布恩(Gary Buyn),2011年
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.