服务器128Tick,也就是一秒钟要跑够128帧。
7.8125ms一帧,分配给包括:
网络:网络占用很少,1ms不到,主要包括
手撸一个网络通信框架
物理
逻辑
前言:其实无非就是客户端驱动、服务器驱动、客户端预测/回滚、客户端插值、延迟补偿。
移动同步,服务器同步位置后
客户端直接设置。卡顿、延迟
影子追逐。有惯性,不跟手。速度快了,有跳跃;速度慢了,不跟手。
Snapshot:Delay需动态设置,太高了滞后性,太低了跳跃性。根据最近Delay动态调整。
客户端先行
服务器:客户端你告诉我你发来的是第几帧
服务器:我会缓存你发来的所有操作帧
服务器:我现在第几帧给你算
A.服务器tick3收到了客户端tick012,服务器算3次
B.服务器tick3收到了客户端tick012,服务器只算tick2
C.服务器tick3收到了客户端tick012,服务器
先看看服务器驱动,我们假设客户端不知道任何信息,只会机械地输入操作。
服务器不走固定tick 客户端不走固定tick。
客户端随操作随时发包。
服务器每次update后根据deltaTime和执行客户端发来的操作更新世界。
MMO常用,FPS不常用。
假设没有网络延迟的情况下,服务器和客户端按照固定128tick帧率前进。 服务器缓存收到的客户端的操作。
服务器Tick执行,t0执行所有客户端t0的输入;把结果返回给客户端,客户端显示结果。
那现在有网络延迟,服务器t0-t5都没有输入,服务器空跑 服务器t6收到了At0和Bt0这时候该怎么办? 服务器t7收到了At1t2t3这时候该怎么办
服务器在t0时刻,如果没有收到某个客户端的t0输入,那么等待,直到全部收到为止。
优点:很公平,对低ping玩家友好。
缺点:对其他玩家不友好,等于所有人都在等网络最差的那个人。
一般1v1格斗、策略游戏适用。
最理想的方式,假设服务器在t=10的时候收到了客户端A t=3的操作,那么把世界回滚到t=3的时候,然后补充客户端A t=3的操作,客户端B t=3的操作没收到,默认为空,再模拟到t=10。
假设t=11的时候又收到了客户端B t=3的操作,那么继续把世界回滚到t=3的时候,然后补充客户端B t=3的操作,再模拟到t=10。
再举个极端点的例子,假设服务器跑了十分钟,也就是t=76800的时候,这时候收到了客户端C t=3的操作,然后服务器回滚到前十分钟,然后补充客户端C的操作后,重新跑十分钟。
优点:很公平。是能够照顾所有客户端的情绪,不会落下任何操作,对延迟高和延迟低的人都一视同仁。
缺点:是服务器回滚压力巨大,回滚后对客户端表现很不好。
服务器预测
服务器某一tick没收到,那么用之前的最近一次的输入
t10收到了t678怎么办
纯客户端回溯的条件是,客户端和服务器执行的tick一致
如果客户端是1234567
但是服务器是1224467
那客户端不可能回溯
所以先信任服务器发回来的 然后回溯
服务器收到客户端发来的包,不要管包里带的tick是多少,那个没卵用,只是用来告诉回客户端“你之前发的那个tick包的结果是xx,自己做移动预测,其他的我不管你”。服务器只管自己的Tick。
为了防止网络抖动,服务器对于每个客户端,给他们设置一个Buffer,这个Buffer是动态的。
缺点是服务器处理会有半个RTT的延迟。
Buffer是动态的,半个RTT。
如果新Buffer大于旧Buffer,那么服务器停下来等待。
如果新Buffer小于旧Buffer,那么服务器多Tick几次。
服务器Buffer 6767之间跳
从6跳到7 多缓存一帧
从7跳到6 之前执行两次,不能执行两次,只能执行最新的一次或者合并这两帧,客户端回滚。
频繁回滚。
buffer不要频繁跳跃。Buffer不要每时每刻都改变
Socket建立的TCP连接不勾选NoDelay的话,用Clumsy设置Delay为1ms都很卡;设置NoDelay之后,正常了。
低延迟玩家是否会比高延迟玩家更有优势 还是相反?为什么
延迟补偿。没有行不行?不可能
探头优势。专用网。高tick。客户端高fps
服务器每隔128Tick更新世界,更新客户端位置,然后下发快照给客户端;
经历半个RTT+客户端Buffer后,
客户端收到最新位置,更新最新位置
服务器这时候已经Tick很多次了,服务器位置更先。
这时候客户端开火;
经历半个RTT+服务器Buffer后,
服务器这时候已经Tick很多次了,服务器位置更先。
在服务器看来,客户端瞄准的是RTT+客户端Buffer+服务器Buffer之前的位置。
那怎么办呢?
客户端开火包到服务器后,服务器找到之前的快照。回溯1个RTT+客户端Buffer+服务器Buffer。不合理,RTT是动态的,双边Buffer也是动态的,可能出现回溯偏差情况。
客户端开火带上服务器Tick,服务器回溯到Tick时刻。
开火的人的位置要不要回溯?不用
还是有个问题,客户端看其他人的位置是Snapshot插值的
服务器启动Tick
服务器下发启动包给客户端
经过半个RTT后,客户端收到包
客户端启动Tick
客户端落后服务器半个RTT
如果网络波动,一开始RTT很长,后续RTT正常,客户端希望追赶
解决办法,服务器每次下发Tick,客户端追赶
因为客户端收到的障碍位置落后于服务器半个RTT,所以客户端本地预测和服务器对不上,频繁回滚。