腾讯游戏开发精粹Ⅲ
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.3.3 预测位置的修正

移动预表现是对主控角色移动状态的一种预测,在复杂的网络环境和游戏机制的相互作用下,预测的误差是难以避免的。从经验上说,在角色位置、朝向和动画状态三个表现要素中,误差最大、对玩家手感影响最大的方面是角色位置。产生误差的原因主要有以下三点。

● 移动与技能衔接:MOBA类游戏中的许多技能在使用过程中会禁止角色进行移动。如图 1.8所示,由于技能没有预表现机制,在预表现移动过程中按下技能按钮,技能逻辑会经过网络延迟的时间才会执行。因此在技能的“禁止移动状态”中,表现层和逻辑层被禁止响应的移动操作可能是不同的。反言之,在整个移动和技能衔接的过程中,被预表现执行的移动操作和逻辑层执行的移动操作也是不同的。

● 表现帧率和逻辑帧率不同:对帧同步游戏而言,逻辑帧的更新间隔是固定的,假设逻辑帧率为每秒15帧,不论当前客户端的表现帧率如何变动,其更新间隔为固定的66毫秒。而表现帧率在不同游戏场景和不同时刻都是不固定的,即使玩家不进行任何操作,表现帧率也会有波动。同时由于网络的波动,每个逻辑帧对应的表现帧更新次数也是不固定的。这导致了同一个逻辑帧对应的所有表现帧累计的更新间隔不是66毫秒,在相同的移动速度下,角色在表现层和逻辑层的位移距离是不一样的。

● 网络丢包:丢包是网络通信过程中的常见问题,对帧同步游戏而言,为了保证不同客户端收到的服务器帧命令的一致性,通常会有一套重传机制保证服务器到客户端的下行传输总是可靠的。然而从客户端到服务器的上行传输不具备这样的特点,上行丢包会导致玩家的移动操作可能不会被服务器收到,也不会在客户端执行对应的逻辑功能。

通常的移动预表现方案会在角色表现层和逻辑层位置差异超过某个阈值时,将角色的表现层位置向逻辑层位置插值移动,从而减少表现层位置和逻辑层位置间的误差。由于插值移动的方向和玩家摇杆移动的方向通常是不同的,所以会对玩家的移动手感造成影响,表现层位置和逻辑层位置的偏移越大,对移动手感造成的影响就越大。在某一时刻,表现层位置和逻辑层位置间的偏移通常由两部分构成:一是由于网络延迟造成的逻辑层位置天然落后于表现层位置的偏移,我们称之为延迟偏移;二是由于移动预表现功能预测误差造成的偏移,我们称之为预测偏移。延迟偏移主要受到网络延迟和角色的移动速度影响,即使预表现预测的移动完全正确,也无法避免;而延迟偏移本身会在经过网络延迟的时间后自然消失,因此将其加入表现层插值移动的计算过程中是没有必要的。

为了消除插值移动过程中延迟偏移对手感的影响,本方案不使用当前时刻角色的逻辑层位置作为插值移动的目标,而是在表现层额外维护一个角色位置,称之为预测逻辑位置,如图1.7中角色脚下的方框所示。预测逻辑位置表示当前时刻所有的摇杆产生的移动帧命令在逻辑层收到后,逻辑层应该到达的位置。当玩家操作摇杆时,如果角色当前可以移动,预测逻辑位置会立即根据摇杆对应的朝向开始移动,从而避免延迟偏移的产生;当逻辑层收到移动帧命令或者使用技能后,预测逻辑位置会立即根据逻辑层位置进行修正,从而减少预测偏移。在每次表现层位置的更新过程中,结合当前的摇杆方向,不断朝着预测逻辑位置插值移动,当经过一定的插值时间后,最终表现层和逻辑层移动的结果应当是一致的。

图1.7 预测逻辑位置示意

1.3.3.1 根据技能状态修正预测表现位置

对于前文中描述的由移动与技能衔接产生的误差,本方案提供了一种方法,在技能的禁止移动状态结束时对预测逻辑位置立即进行修正。在图 1.8中,逻辑层的最终位置满足:

图1.8 技能衔接预测误差示意图

其中,表示“禁止移动状态”开始时刻的逻辑层位置,为已知的变量;为技能本身在逻辑层产生的位移,为已知的变量;表示技能的“禁止移动状态”结束后逻辑层还没有执行的移动位移,对应图1.8中最后的两个红色箭头,此时是未知的变量,无法计算。而在没有技能使用也没有其他误差的理想情况下,逻辑层的移动帧命令产生的位移应当和表现层的预测逻辑位置通过摇杆产生的位移相等,因此有:

其中,表示“禁止移动状态”开始时刻的表现层的预测逻辑位置,为已知的变量;分别表示逻辑层和表现层由于“禁止移动状态”而没能执行的位移,分别对应图 1.8中的红色虚线箭头和绿色虚线箭头,可以在逻辑帧和表现帧更新时根据各自的移动方向计算更新。联立以上两个公式可以得到:

此时的就是在技能的“禁止移动状态”结束时刻修正后的预测逻辑位置。

1.3.3.2 根据逻辑层帧命令修正预测表现位置

对于更一般的情况,本方案使用了回滚的策略,利用逻辑层接收到的帧命令对预测逻辑位置进行修正。虽然在前文中我们明确了帧同步游戏不适合回滚所有的中间状态,但是仅回滚角色的位置信息是可行的。一方面,保存角色的位置信息需要的数据量较小;另一方面,仅修正角色的位置信息不需要将中间的计算过程都重新执行,在不考虑碰撞的情况下只需将终点的位置平移到修正后的位置即可。对于任意一次UI层的摇杆移动操作,要么被下一次摇杆移动操作替代,要么被松开摇杆的操作停止,对应到逻辑层的帧驱动移动命令也是如此。因此,可以用摇杆移动操作对游戏的对局过程进行划分,每一个摇杆操作停止执行时,都记录当时的预测逻辑位置用于回滚,如图1.9所示。

图1.9 预测逻辑位置队列

令记录的预测逻辑位置队列为,每当摇杆移动操作对应的逻辑层移动帧命令停止生效时,对记录的预测逻辑位置进行修正,如图1.10所示。摇杆1对应的移动帧命令结束时,逻辑层的位置为,可以计算出我们对的预测误差矢量为。此时从队列中删除,将剩余记录的预测逻辑位置都平移,完成一次修正。利用逻辑层移动帧命令不断地对预测逻辑位置进行修正,可以保证最终预测逻辑位置的正确性。

图1.10 帧命令修正预测逻辑位置