您的位置:首页 > 其它

快速多人游戏(3) - Entity插值

2016-06-16 16:27 176 查看
http://blog.csdn.net/silangquan/article/details/51532399

原文链接:Fast-Paced Multiplayer (Part III): Entity Interpolation


介绍

在系列的第一篇文章中,我们介绍了一种权威服务器的思想还有他在防止玩家作弊方面的优势。但是直接使用这种技术会引起可玩性和响应性方面的问题。在第二篇文章中,我们提出了一种客户端预测的方法来处理。

到现在为止我们提出了一套解决方案,能够让玩家在多人游戏中得到单人游戏般流畅的体验,即使是在接入权威服务器并且有一定网络延迟的情况下。

在这篇文章中,我们将会处理当有别的玩家连入相同的服务器的问题。


服务器时间步长

在前面的文章中,服务器的行为非常的简单 - 读取客户端的输入,更新游戏状态,然后将结果返回给客户端。当超过一个客户端连接的时候,服务器的主循环逻辑就有点不一样了。

在这种情况下,一些客户端可能同时快速地发送输入(比如按方向键,移动鼠标或者单击),每次收到客户端的请求就更新游戏,然后再把结果进行广播, 这样会消耗大量的CPU和带宽。

一种好的方式是将玩家的输入压到队列中去而不马上进行处理,服务器在一定的频率上进行相对低频率的更新,比方说没秒10次。每次更新之间的时长称为时间步长,在这里是100ms。在每次的更新迭代中,所有的未处理的输入都依次处理(可能会比时间步长更小一些,来让物理更可预测一些)然后新的游戏状态就广播给所有的客户端。

总的来说,游戏世界的更新应当在一种可预测的频率,独立于玩家的输入。


处理低频率的更新

从玩家的角度看,这种方式还是像之前的方法一样顺滑 - 客户端的预测独立于更新的延迟,所以对于可预测的状态更新是没有问题的。但是,因为游戏状态以一种低频率进行广播,这将导致游戏看上去非常卡顿,可能是100ms更新一次位置。



在客户端2中看到的客户端1的情况

根据你开发的游戏类型,可能有很多方法来处理,通常你的游戏实体越可预测,越好处理。


航位推

假设你在做一个赛车游戏。一辆快速开着的车是非常可预测的 - 假设他的速度是100m/s,那么1s之后,它应当大致在离起始点100m远的位置。

为什么是“大致”?因为在这一秒中之内,车可能加速一点,也可能减速一点,向右一点或者向右一点 - 这里说的是一点点。由于车的机动性,车的当前位置总是依赖于它之前的位置,速度和时间。而不是玩家的输入,换句话说,一辆快速运行的车没法瞬间180度掉头。

一个每秒更新10次的服务怎么来处理呢?客户端收到每辆车的速度和朝向之后,在接下来的100ms内,它不会受到任何新的信息,但是客户端还是要进行更新啊。最简单的方法就是假设车在这100ms内,朝向和加速度都是常量,然后让这辆车继续运行,100ms之后,收到更新包之后,再对车的速度进行纠正。

纠正可能很大也可能很小,依赖于很多因素,如果玩家保持直线运行并且不改变车的速度,那么预测的结果和正式的位置是完全一致的。另一方面,如果玩家撞到什么东西,预测的位置就完全错了。

有一点要提一下,航位推的算法可以应用在慢速的情况下 - 比如战舰。其实这种算法最初就用在海上导航。


Entity插值

有许多情况航位推是没法处理的 - 对于玩家的方向和速度可以瞬间改变的都不行,比如3D射击,玩家经常快速跑动,停下,快速转向等,在这种情况下,航位推算法就非常无力了。因为位置和速度和前面的数据无关。

你可以选择在接到服务器的请求的时候直接更新玩家的位置,而客户端看到的就是网上其他的玩家每100ms跳一下,感觉会非常奇怪。

你现在拥有的是每100ms由服务器传送过来的权威数据,现在要做的是如何在这100ms内让网络角色看起来非常自然,解决问题的关键就是将网络玩家显示在过去的某个时刻。

假设你在t=1000收到位置信息,你已经在t=900收到了一次位置信息,所以你知道玩家在t=900和t=1000的位置,所以在t=1000到t=1100之间,你只要显示玩家t=900到t=1000的位置。这种方法,你所显示的都是玩家的真实数据,只是有100ms的延迟。



客户端2渲染的是客户端1的角色过去的位置,利用插值来更新位置

用来插值的t=900和t=1000的数据依赖于游戏。插值通常都可以处理得很好。如果不是这种方法,你可能需要服务器发送更加详细的移动信息了 - 比如更多的位置采样点,或者每10ms发送一次(你不必发十倍的数据 - 因为你发的微小的位移数据,在这种情况下数据的格式可以很好的优化一下)。

当使用这种技术的时候,每一个玩家都和游戏世界有一点点不同步,因为每个玩家看到自己的世界是当前的,但是其他的玩家都是过去的。但即使是快速的游戏,这100ms的延迟都不是那么明显。

有一种情况除外 - 当你需要时间和空间的准确性的时候,比如一个玩家射击另一个玩家的时候,因为其他的玩家都是存在于过去的某个时候,你的瞄准其实是有100ms的延迟的 - 也就是说,你设计的目标是100ms的某个目标! 这个问题我们下一篇会进行讨论。


总结

在权威服务器的环境中,有着不确定的服务器更新和网络延迟,在这种情况下你还要给玩家平滑的移动。在第二篇中,我们展示了一种客户端预测和服务器调和的技术,来实现实时的角色控制,这样的方案让玩家能够得到即时的反馈,移除了致命的延迟。

其他玩家的同步还是一个问题,但是,在这篇文章中,我们提出了两种解决方案。

第一种是航位推技术,这种模拟需要entity的位置能够通过前一个时候的位置,速度,加速度来推算出来,当不满足这种情况的时候,航位推就没用了。

第二种是插值技术,不预测将来的位置,只是使用服务器传来的数据,这种就会造成显示的entity总是过去的某个时刻。最后的结果就是玩家的角色总是当前时刻,而其他看到的entity都是过去的某个时刻,这种情况可以产生一种难以置信的无缝体验。

但是,当游戏需要高速离散的准确性的时候,比如射击或者移动物体,美景就破灭了:你看其他玩家的位置和服务器的位置不一致,别的玩家看你的位置也不是正确的,这样爆头就不可能发生了!很多游戏都有爆头这一说,我们将在下面的文章中来讨论这个问题
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: