FPS游戏同步相关

作者:腾讯天美工作室群
链接:https://www.zhihu.com/question/29076648/answer/1946885829
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 

同一局游戏内,每个客户端和服务器都各自是一个独立的世界。理想情况下,所有世界都应该是同步的、一致的,在任一给定时刻,玩家在每个世界中的位置和姿态都应该是相同的。然而由于延迟的存在,这种理想情况却不可能实现!

尤其在射击游戏中,因为射击游戏给玩家的反应时间极短,1秒就能决定生死,职业玩家甚至对10毫秒的延迟都会非常敏感,所以在游戏中如果人物的移动忽快忽慢,甚至还有位置瞬移,玩家的射击体验就会大打折扣。

今天我们邀请到了来自天美的游戏后台开发Walter,他将从技术角度分享自己解决延迟问题的经验:在射击游戏中,我们要如何与延迟抗争,做到更好的体验?

1. 认识游戏中的延迟

网游都是采用典型的C-S通信模式,客户端必须持续地与服务器通信才能正常运作,网络通信的round-trip time明显就是我们不想要的延迟。网络传输的丢包、重传等,都可以纳入网络延迟的范畴。

但游戏中的延迟远不止网络延迟这么简单,计算机系统(包括手机)的运作、游戏的实现机制都会引入延迟。

点击鼠标产生开火指令,这个电信号的传输、被系统捕获都需要时间,客户端逻辑线程通常要到下一帧才会开始处理这次输入,逻辑处理中抛事件到渲染线程,渲染线程最快也要下一帧才能去渲染结果,渲染结果要显示到屏幕上又受限于屏幕的刷新率。

可见,即使是没有网络的纯客户端游戏,延迟都不可避免地存在。很多游戏在实现中会用到Buffering技术,这还会进一步加剧延迟。

衡量游戏品质的一项重要指标就是玩家常说的“手感”,而手感的关键组成部分就是反馈的及时性。对于射击游戏、竞速游戏,玩家对手感有着极高的期待,职业玩家甚至能感知到10ms级别的延迟差距,所以游戏开发者都会在这方面下很大的功夫。

2. 降低网络延迟

网络游戏中,网络延迟是延迟的主体部分,降低网络延迟是优化体验的关键,也是开发商都会重视的地方。例如,由Riot Games开发的第一人称射击游戏《Valorant》就做到了为70%玩家提供小于35ms的RTT。

2.1 搭建专用网络

网络包在传输中要经过复杂的路由,这导致了高延迟以及更多的不确定性。所以,有实力的厂商都会在网络基础设施上做投入,例如Riot有去搭建自己的ISP。这一点可以简单理解为:厂商会围绕玩家就近部署很多接入服务器,内部的服务器之间由专用的高速通道相连,就像修了很多专用的高速公路,所以整体的通信非常稳定、高效。

2.2 使用UDP

越来越多的游戏都从TCP转向了UDP,在剔除/简化了拥塞控制以后,包传输的及时性有了明显的提升,尤其是在弱网环境下。

由于UDP不可靠的特性,一般都会实现Reliable-UDP。实际游戏中,一般会混用可靠与不可靠的UDP,纯表现的消息、状态同步等可能会用不可靠的UDP,用户输入、逻辑事件等重要的信息则会用可靠的UDP。

3. 使Buffer尽可能小

3.1 Buffering机制

网络游戏中,客户端和服务器几乎每一帧都在通信,玩家的操作永远来自于客户端,权威的信息永远来自于服务器。但网络通信是不稳定的,服务器可能连续5帧都没有收到客户端A的数,但在下一帧又一口气收到5个。这种输入的缺失和爆发增长会导致卡顿,导致不平滑的游戏体验。无论是帧同步还是状态同步,都会面对这个问题。

经典的解决办法是使用buffering机制:增加一个buffer,缓存几帧数据以后再以稳定的频率向业务系统提供输入。这个机制良好地解决了网络传输带来的输入抖动问题,网络视频播放器中一直在使用该技术。

3.2 缩小buffer

很多游戏中都有用buffering机制,它确实让游戏变得平滑了,但却以增加延迟为代价。追求极致体验的游戏都不得不在buffer的大小上做折中,有的只存1帧的数据,有的甚至完全消除buffer。

缩小buffer的同时还要保证平滑的游戏体验,这意味着游戏要提供非常稳定的帧率、避免毛刺,还必须要在没有输入的情况下自己去预测玩家的行为。

假设玩家在持续地移动,客户端每帧都在上报移动指令,后来由于网络故障,服务器在几帧内都未收到新的移动指令,这时服务器要尽最大的努力去预测,从而使网络恢复以后 玩家的移动仍然是平滑的。

4. 更高的帧率

帧率的影响到底大不大?帧率高到一定值以后 是否值得继续提高?这是一个有一定争议的话题。

油管上有一个高帧率对玩家表现的对比测试,感兴趣的同学可以观看一下。

视频地址::https://youtu.be/OX31kZbAXsA

不管是否值得,但毫无疑问,更高的帧率必然是有好处的。帧率越高,系统运作的延迟就越低,响应越及时,表现也会更平滑、更自然。客户端帧率超过100的游戏并不少见,但服务器帧率几乎都小于64。服务器的帧率有必要更高吗?

Riot说有必要,《Valorant》的服务器是以128帧运行的,这让人印象深刻。客户端与服务器都在模拟角色的移动,它们的运算结果会无可避免地出现分歧。假设服务器是1秒1帧,两端位置的最大分歧是1米,然后被强制纠正到一致。若两端都是1秒128帧,两端位置的最大分歧可能就只有10厘米了,然后也被强制纠正到一致。

帧率高了就像是小步快跑,每次产生很小的误差,然后不断地纠正,所以整体的表现会很平滑。另一方面,即使某个客户端只以60帧的频率上报移动指令,其他9个客户端仍然可以以128帧的频率收到服务器下发的位置更新,所以 其他9个人看到的人物移动仍然是非常平滑的。

在《Valorant》中,客户端与服务器的移动和物理都是保持128帧运行的,这使得两端的每一帧都可以 一一 对应上,这极大地方便了服务端的命中判定,服务器只需把其他人的位置回退固定的帧数,就可以与客户端上的位置匹配。

《Valorant》

高帧率缩短了系统运作的延迟,提供了更加平滑、细腻且一致的角色移动,这对FPS游戏是很有意义的。射击游戏给玩家的反应时间是极短的,1秒就决定了生死,职业玩家对10毫秒的延迟都很敏感。

每个人都是非常平滑地移动,这是很利于玩家追踪和预测对方移动轨迹的,所以玩家的射击体验会好很多。要是人物的移动忽快忽慢,甚至还有位置瞬移,玩家的射击体验就会大打折扣。

但是,一切皆有代价。要做到这样的高帧率本身就很困难,需要花很大的力气去优化性能。就算技术上做到了,服务器运行的成本也是非常高的。

5. 状态同步+客户端预测+纠正

帧同步要求每个客户端的运算输入严格一致,这样才能保证每个世界始终处于一样的状态。这意味着它们的输入一定来自于同一个服务器,意味着玩家输入到逻辑执行之间要包含网络延迟,这个延迟通常是几十毫秒,这会立即让玩家觉得“游戏的手感不好”。

FPS游戏大多都是使用状态同步,因为这样很容易做客户端预测,从而实现更好的及时性。玩家按键操作之后,客户端把该输入发给服务器,同时客户端本地直接处理该输入、产生部分结果/表现,而不用等待服务器的返回,这就是客户端预测

服务器处理完输入以后会通知客户端结果,如果本地运算结果与服务器下发的不一致,肯定要以服务器的为准,故客户端要做纠错处理。

由于是状态同步,即使客户端本地计算出错了,也总是能恢复到一致的、正确的状态,UE引擎的移动同步就是这样做的。

6. 隐藏lag

对于网络游戏,重要的信息必须以服务器为准、不能客户端自主决定,否则会外挂泛滥,例如子弹命中的判定、造成的伤害量、技能的生效等等。但如果玩家的输入总是要等服务器返回后才给玩家反馈的话,玩家会觉得游戏的体验很差。公平性与及时性都很重要,但却存在冲突,需要我们做一些细致的特殊处理。

6.1 扔手雷

接下来,我们来看一个实际的例子(此处的例子节选自由微软发行的第一人称射击游戏系列《光环(Halo)》的分享)。假设玩家扔手雷的粗略过程如下:

按键是客户端行为,前摇动画可以看作是一段固定的延迟,飞出手雷代表施法的正确结束、产生了效果。

我们是网游,生成手雷这么重要的事情当然得服务器说了算,所以我们会很自然地这样做:

图中黄色的文字标记出了延迟的位置,玩家按键以后 隔一段时间才出现前摇动画,这体验当然是不可接受的,我们要更早地给玩家反馈。

想要及时反馈,可以在按键后直接播前摇动画,并且在时间结束后直接飞出手雷:

这违背了服务器做决策的原则,明显更无法接受。服务器上前摇过程还未走完,但客户端已经飞出手雷了,若服务器上前摇过程被他人打断,客户端必须要把已经飞出的手雷给删掉,这种诡异的表现会让玩家非常困惑和不满。

《Halo》最终的实现方案是:

按键后,客户端立即播放前摇动画,但等服务器流程结束后再通知客户端飞出手雷。相当于在客户端把前摇给拉长了。这样做解决了上述问题,提供了良好的用户体验:

● 玩家按键后立即获得了反馈,所以操作体验很好。

● 手雷的生成遵从了服务器的权威,杜绝了被打断导致的奇怪表现。

● 虽然手雷的飞出有延迟,但动画末尾的手臂占据了大部分画面,玩家几乎感知不到这个延迟。即使玩家发现了这个延迟,影响也不大。

6.2 开启无敌

另外一个例子,是《Halo》中释放无敌技能的过程。我们仍然期望按键后就立即播放前摇动画,但却不能再像上面一样延迟出现无敌效果。

因为无敌状态对施法者太重要了,晚0.1秒就可能是生与死的差别,玩家对这段延迟非常在意、几乎无法容忍。这时还可以把延迟藏在哪呢?

为了给施法者提供极致的体验,这里修改了游戏机制 —— 把服务器端的施法延迟给缩短了,即把网络延迟藏在了这里。

这种修改游戏机制的做法是特例,应该谨慎使用。虽然施法方的体验变好了,但对他的对手是不公平的。这里之所以可以这么做,是因为玩家普遍不能接受自己的无敌晚一点出现,但却相对能容忍对方的无敌早一点出现。

7. 在割裂的世界中愉快地玩耍

7.1 屏幕上看到的都是假象

我们再来看看射击游戏中的经典问题 —— 命中判定。延迟的存在,使这个问题变得更加棘手。

子弹是否打中敌人、打中的部位是头还是脚,这些都是非常关键的信息。命中的判定可以在客户端做,然后服务器做校验,也可以只在服务器做。无论用哪种方式,我们都必须要面对一个事实:玩家屏幕上看到的敌人位置,很可能不是此刻敌人的真实位置,或者说不是其他世界中对方的位置。

同一局游戏内,每个客户端和服务器都各自是一个独立的世界。理想情况下 所有世界都应该是同步的、一致的,在任一给定时刻,玩家A在每个世界中的位置和姿态(Pose)都应该是相同的。但由于延迟的存在,这种理想情况永远都不可能实现!

一个简化后的、现实中的模拟如下图:

一个框代表游戏运行的一帧,图中只画出了部分帧,并假设客户端与服务器的逻辑帧能稳定地一一对应。红线代表客户端上报的自己当前帧的位置/移动,蓝线代表服务器每帧下发的其他角色的位置/移动。假设A和B都在持续地移动:

l t1时刻,客户端A把自己本帧移动的结果(PAe)上报给服务器,客户端B同样把PBe上报给服务器。

l t2时刻,服务器上A和B的位置分别为PAe和PBe。服务器把当前帧的位置信息同步给所有客户端。

l t3时刻,客户端A收到玩家B的位置为PBe,但自己已经移动到了PAi。

这是很多游戏的角色位置模拟过程,在任一时刻,客户端看到的自己的位置始终是领先于服务器的,但看到的其他人的位置又都是落后于服务器的。这导致——战斗中,我们始终是在用将来位置的自己去打过去位置的敌人。例如客户端A在t3时刻瞄准了B,并开枪射击,服务器收到射击事件时已经是第i帧了,但t3时刻和t4时刻 玩家B在服务器上的位置都不是PBe。

假设命中判定在客户端做,t3时刻客户端A认为自己打中了B,但服务器需要校验这一次射击的合法性,服务器收到射击事件时 玩家B的位置已经变成PBi了,这时服务器很可能认为A打不中B。把命中判定交给服务器来做,仍然有同样的问题。

不同世界间的不同步是由延迟导致的,延迟导致的结果是:只要敌人持续在移动,并且移动速度比较快,你瞄准后的射击永远也打不中敌人。

7.2 服务器回退玩家的位置

解决命中问题的经典方案是 —— 服务器做玩家位置回退。服务器记录一段时间内每个人的历史位置和Pose,收到A的射击事件时,服务器把A之外的所有玩家都挪回到一个恰当的历史位置去,使服务器上其他人的位置与A看到的其他人位置基本一致。这样,客户端上能打中的 服务器上就也能打中了。如图所示:

但这种方案也有问题:它对被打的那一方不公平。例如t3时刻,玩家B明明已经躲起来了,在客户端B的世界里 玩家A是打不到自己的(位置PAe与位置PBi),结果你t3时刻的开火还是打死了自己。

要解决这个问题,一般是给回退的时长加一个约束,例如最多只允许回退一个RTT。

8. 让网络卡的人自己拉扯

UE4默认的移动同步过程是:客户端和服务器都模拟角色的移动,客户端每帧上报自己移动后的结果和当前的移动输入,服务器收到移动输入后也去模拟移动。

若服务器的移动结果与客户端上报的结果误差在一定容忍范围内,则直接采纳客户端的结果,使服务器上玩家的位置等于客户的上报的位置。若误差超出了容忍范围,则以服务器为准,强制重置客户端的位置。

当容忍范围设置得较大的时候,服务器上会大幅度重置角色的位置,当同步到其他客户端以后,这个角色的移动必然会出现波动,要么是直接位置重置,要么是插值过去(加速移动过去)。无论用哪种处理方式,最终的结果都是:一个玩家B卡了,然后其他9个人看到的B的移动都是不平滑的。

Valorant认为:一个人卡了,却导致其他9个人的瞄准体验变差了,这是不可接受的。对应方案是:若服务器未收到移动输入,仍然根据当前的状态每帧做预测,当出现分歧时始终以服务器的模拟为准,并且每帧都下发角色的位置。

这样做,无论个人怎么卡,其他9个人看到的角色移动始终是平滑的,但卡的那个人自己会被频繁地拉扯。

9. 解决Peeker’s advantage

9.1 什么是Peeker’s advantage?

这是战术射击游戏的经典话题,玩家在转角处来回晃悠可以获得先手优势(会先看到对方),是一种网络延迟导致的不公平现象。

动图封面

如图所示,冲出角落的人会先看到对方,而蹲角落的人明显要晚一些看到对方。说明:这里是用了比较大的ping值来演示该效果,实际中不一定有这么明显。

产生这个问题的本质原因就是网络延迟,正如上面已经讲过的:若是自己在移动,自己客户端上自己的位置是领先于其他所有世界的,而静止不动的人的位置在所有世界中都是一致的。移动的人的位置要同步到其他客户端,这是需要经过网络传输的:

动图封面

9.2 它到底有多大的影响?

这个优势其实是可以用数学公式来描述的:

如图,holder要想打赢对方,就必须要在server applies kill shot之前把开火指令发送到服务器,这样才能实现比peeker先开火。进而可以得到这样的关系:

holder reaction time < peeker reaction time - (holder RTT + holder buffering latency + server buffering latency)

所以peeker方领先的时间主要取决于holder方的网络延迟,以及buffering延迟

更进一步,我们可以带入具体的数字来量化这个优势。按帧率60、单边通信30ms延迟来算,peeker方大约可以获得140ms的先手优势。

9.3 技术层面能做什么?

① 降低网络延迟。无非就是就近部署、搭建高速专用网络、使用UDP,上面已经讲过了。

② 降低buffering延迟。最小化buffer大小,上面也已经讲过了。

③ 高帧率也是有帮助的。在Valorant中,如果客户端能跑140帧的话,这个差值可以降低到71ms。

9.4 从设计的角度弱化Peeker’s advantage

技术上没办法彻底杜绝这个问题,而且也很难取得明显的改善,至少代价是很大的。但从设计上 我们有很多方法来优化它:

● 地图设计:例如一个区域只留一两个进入的入口(供他人peek around),但场地内有多个地方可以设伏、蹲守入口。这样的设计使得holder的位置高度不确定,但peeker的位置高度确定,变相地增加了peeker方的难度。

● 降低移动中射击的准确率。在这一点上每个游戏的取舍都不同,Valorant在这方面做得比较狠,移动中几乎很难打中。

● 让peeker的身体先暴露,但相机晚一点暴露。这使得peeker先暴露出自己的部分身体,然后相机才能看到holder。人的移速慢一点、系统运行帧率高一点、身体做大一点,都会有利于peeker先暴露出部分身体。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
- Added Grenades - Bug Fixes - Adapted to new Photon Updates EZFPS is a multiplayer first person shooter template for Unity3d, using Photon Unity Networking. EZFPS is designed to make a simple FPS Deathmatch style game, with Ai bots, zombies, player classes, weapon loadouts, weapon skins and attachments, and player customization. As the player gets kills, they receive XP points, in-game currency, and rank up- allowing them to buy and unlock new weapons, attachments, skins, and cosmetics. The kit comes fully setup with 5 maps, a zombie-only mode, 9 weapons, and 3 classes, but an infinite amount of maps, weapons, and classes can be added easily by following the included tutorials and documentation. Youtube | Demo | Docs | Tutorials Features: - Player Classes - Synced Bot Ai - Synced Zombie Ai - Custom Loadouts - Player Cosmetic Customization - Weapon Attachments and Skins - Rank System - Weapon Unlocks - Machine Guns, Sniper Rifles, Shotguns, Knifes, Rocket Launchers, Grenade Launchers - Grenades - Settings Menu - More! 谷歌翻译: ——添加手榴弹 ——错误修复 -适应新的光子更新 EZFPS是一个多玩家的Unity3d第一人称射击模板,使用光子统一网络。EZFPS是设计来做一个简单的FPS死亡比赛风格的游戏,与Ai机器人,僵尸,玩家类,武器加载,武器皮肤和附件,和玩家定制。当玩家获得技能时,他们将获得经验值、游戏内货币和等级——允许他们购买和解锁新的武器、附件、皮肤和化妆品。这个工具包有5张地图,只有僵尸模式,9件武器和3个职业,但是无限数量的地图,武器,和职业可以很容易地添加遵循所包含的教程和文档。 Youtube |演示|文档|教程 特点: ——玩家类 -同步机器人Ai -同步僵尸Ai ——自定义面板 -玩家化妆品定制 -武器附件和皮肤 ——排名系统 ——武器解锁 -机关枪,狙击步枪,猎枪,刀,火箭发射器,手榴弹发射器 ——手榴弹 ——设置菜单 - - - - - -更多!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值