FPS游戏中游戏同步性的实现-UNIT3D游戏外包

FPS游戏中游戏同步性的实现-UNIT3D游戏外包

2 years ago 0 11723

何为延迟补偿?如何进行坐标差值?B客户端屏幕上A已经跑到东边了,但是收到服务器说“A正在西边往北跑”,B到底该何去何从?我若干年前的一个实现版本,将简明扼要的解决这个问题:

影子跟随算法由普通DR(dead reckoning)算法发展而来,我将其称为“影子跟随”意再表示算法同步策略的主要思想:

屏幕上现实的实体(entity)只是不停的追逐它的“影子”(shadow)。

服务器向各客户端发送各个影子的状态改变(坐标,方向,速度,时间)。

各个客户端收到以后按照当前重新插值修正影子状态。

影子状态是跳变的,但实体追赶影子是连续的,故整个过程是平滑的。

前面的1号终端控制红色飞船P1向左飞,并把自己的状态时时告诉服务器。

后面的2号终端上接收到飞船P1的影子S1的状态(向左移动),并让P1的实体追赶S1。

网络性能指标一:带宽,限制了实时游戏的人数容量。

网络性能指标二:延时,决定了实时游戏的最低反应时间。

使用该算法可以容易的开发出一款马里奥赛车,或者Counter Strike,详细说明见后:

算法比较:

帧间同步:不同客户端每帧显示相同的内容,键盘/时钟数据传到服务器,服务器确认后所有终端做出响应,多用于局域网游戏,比如红警(需要等待客户端),街霸II的网络版(360),可参考 LockStep,TimeWrap算法,网速要求高,复杂度低,见我的旧文帧锁定算法。

插值同步:不同客户端显示不同步,但是状态同步,常见的Dead Reckoning(或叫导航插值),效果好,但复杂度高。常见于竞速类游戏和 FPS游戏。

算法定义:

时间:单位为帧(FPS=10),开始由服务器告诉向所有客户端,每5分钟同步。

玩家:每个玩家控制自己的实体,并在每贞将状态改变告知服务器。

状态:状态数据 = 实体ID + 坐标 + 方向 + 速度 + 时间(贞)。

插值:收到新状态包后将根据其运动方向与时间,根据现有时间计算新状态。

跟随:实体不停的追踪自己的影子,追上后与影子保持状态同步。

相位滞后:可选参数,实体与影子保持一定距离同步,相当于保持一定车距,这样在控制者突然停止的时候,不容易因为网络延迟跑过了又被拉回来。

惯性移动:可选参数,开始移动或者停止或者改变方向都有加速度,这样就不需相位滞后了。

每次服务器向各个客户端同步时间的时候,由于延迟,所有客户端的时间都是慢于服务器的,这没有关系,只要大家在一定误差范围内以相同的速度增加,就完全没有问题。

在公网平均130ms的Latency下,是不存在“完全的”的同步情况。如何通过消除/隐藏延时,将用户带入快速的交互式实时游戏中,体验完美的互动娱乐呢?

让所有的用户屏幕上面表现出完全不同的表象是完全没有问题的;

把这些完全不同表象完全柔和在一个统一的逻辑中也是完全没有问题的。

需要根据具体情况,分清楚哪些我们可以努力,哪些我们不值得努力,弄明白实时游戏中同步问题关键之所在,巧妙的化解与规避游戏,最终在适合普遍用户网络环境中(200ms),实现实时快速互动游戏。

案例解析:Counter Strike

实现CS的话,首先我们需要给人物移动加上惯性,比如静止状态突然开始移动,那么需要0.5-1秒的加速过程,而移动中突然停止也需要0.5-1秒的减速过程,这样就实现了无差别同步,不需要相位滞后来避免拉扯影响用户感。

同时开枪射击采用客户端判断,也就是说如果我看见你在墙前面,开枪射中,那么我向服务器发送“我击中你了”,这时有可能真实的你在墙后,那么表现出来的就是我看见我打中你了(减不减血由服务段判断),而你没有看见我,觉得我穿墙打中你了。