c++ - 游戏网络代码-客户端预测和修正

标签 c++ networking winsock

我正在使用 winsock 和 c++ 创建一个 2d sidescroller mmorpg,我想问一下如何编写客户端预测和校正程序? 好吧,尤其是更正,因为预测基本上只是在客户端运行您在服务器上运行的物理代码。 服务器大约每两秒发送一次更正。此消息包含 X & Y 位置和 X & Y 速度以及类似的输入 左0,右1,跳1...

编辑: 我可以为其他客户做同样的事情吗?所以我没有发送位置和速度的快照,而是只发送已经改变的输入,以及本地 客户端将预测其他客户端将移动到哪里。服务器每 2-3 秒发送一次更正。

非常感谢!

最佳答案

通常在这种类型的游戏中会做什么:

  1. 预测是“航位推算”,其中服务器让客户端以恒定速度移动(当然会根据重力、爆炸和服务器上发生的任何其他情况调整此速度),直到客户端更新其当前位置和速度。对于 Action 游戏,很难想出比这种速度*时间运动更高级的预测(即试图预测即将到来的输入)。

  2. 告诉服务器您所在的位置是一件棘手的事情。如果服务器依赖于玩家发送他们自己的位置和速度,客户端可以欺骗他/她的位置来绕过障碍。理想情况下,服务器只接收客户端输入并直接处理由此产生的移动,因此可以确定人们以合法的方式移动。然而,将输入输入到服务器的延迟使得这变得不切实际,因此您可能需要一个中间立场解决方案,客户端说“当我将速度更改为(s,t)时,我就在(x,y)”(即在 x,y 点按下了跳转键,服务器查看此信息并说“根据我对该客户的预测 Action ,他实际上在 0.7 秒前就在那个点附近,所以我相信他真的做到了在那一点将他的速度更改为 (s,t)。我对最后 0.7 秒的预测不准确,所以玩家实际上处于 (x,y) + (s,t)*0.7"如果服务器不同意,它应该告诉玩家它认为她或她当前所在的位置,以便玩家快速回到服务器指示的位置。例如,如果在客户端的输入到达服务器之前服务器发生了爆炸,那么客户端对自己在世界上的看法就不再准确了。同样,如果客户试图发送一个远离他当前位置的错误位置或一个荒谬的高移动速度。可以说,服务器必须放下打击:)

  3. 服务器向每个客户端发送每个玩家在他或她附近的位置和速度。位置和速度足以完全预测和推断玩家的移动。换句话说,其他玩家不关心按下了哪些键或类似的东西,服务器已经确认了准确性。 NPC Action 和AI可以在客户端处理,不需要发送。

  4. 网络游戏几乎总是使用 UDP 套接字完成。 UDP 套接字的开销比 TCP 低得多,因为接收方不确认数据包。如果他们迷路了,他们就永远消失了。虽然这节省了确认往返行程,但您不能假设数据包曾经到达服务器,反之亦然。这是发送输入事件的棘手之处。始终发送当前状态“快照”而不是状态更改是理想的,因为即使数据包在传输过程中丢失,只要数据包进来,您就会知道正确的状态。换句话说,您总是想说“这就是我所在的位置和我目前正在做的事情”,而不是“我按了 3 次跳跃键”。

总而言之,客户端可以发送速度更新以及变化发生时化身所在的位置。服务器验证所有当前状态的合理值。服务器将此数据发送给附近的其他玩家(理想情况下将附近玩家的所有运动信息打包到一个数据包中),客户端应用相同的预测模型减去合理运动的验证。

对不起,如果这太长了......

关于c++ - 游戏网络代码-客户端预测和修正,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8703910/

相关文章:

c++ - 类中的 setter 不会设置变量

c++ - clang 3.3 和 constexpr 约束

linux - 使用可预测的网络接口(interface)名称

c# - 无法使用 System.Diagnostic.Process 运行 nbtstat

c++ - 为什么在打印消息时名称会打印两次?

c++ - 同步套接字send()

c++ - winsock2重新定义合并问题

c++ - std::ofstream 即使在二进制模式下也写入\r

c++ - 在 C++ 中复制和操作大型密集二维数组的最快方法是什么

c# - 试图将 uint16 打包成字节数组 C# 的 2 个字节