游戏中的网络同步机制<一> 帧同步Lockstep

参考游戏中的网络同步机制——Lockstep

一、前言

每个人或多或少都接触过网游,那个虚拟的世界给予了我们无穷的乐趣,而这个虚拟世界是如何完美的将身处天南地北的玩家连接在一起的呢?我们每个人的电脑配置都不一样,网络延迟也不同,但是在玩FPS(第一人称射击)游戏时,战斗感受与真实世界并无二致,网游是如何做到这一点的呢?

本文将介绍和分析早期广泛在RTS(即时策略)游戏中应用的同步机制——Lockstep

RTS游戏有很多,比如我们都玩过的的Warcraft III(大家耳熟能详的Dota是它的一张地图)和StarCraft,还有EA的代表作命令与征服系列(Command & Conquer)等等,以及现在非常流行的Dota2和LOL

那么为什么要强调早期呢?因为Dota2和LOL等新兴的游戏使用的同步机制不再是传统的Lockstep了。严格来说,Warcraft和现在意义上的网游有很大区别,因为它所谓的网是局域网(LAN)。早期RTS游戏出现时互联网还没有现在那么普及,网速也很慢,更没有什么像样的网游,能够支持局域网对战已经很不错了。

有人可能会有疑问,我们平时经常在对战平台上和全国各地的人打Dota,你为什么说Warcraft III只支持局域网呢?这又是一个很有意思的话题,实际上,对战平台使用了虚拟局域网(VLAN)技术,通过进程注入,HOOK WinSock函数调用,将数据包发送到对战平台服务器上,由服务器分配虚拟IP,这里还能够进行天梯匹配等等,在随后的游戏过程中游戏数据包都是通过对战平台的服务器进行转发,但是这一切对Warcraft III进程本身来说是透明的,它依然感觉自己在一个局域网环境中。

二、为什么要有同步机制
1. 一致性

在虚拟世界中,保证游戏的一致性是一个基本前提。什么是一致性?通俗的说就是虚拟世界中的事实,比如在一个FPS游戏中,大家的延迟都很高,A、B两个玩家同时发现了对方,并向对方射击,如果没有很好的同步机制,那么A的屏幕上显示B还没有开枪就被击杀,而B的屏幕上显示A还没有开枪就被击杀,这就出现了不一致的问题,那么这个游戏还怎么愉快的进行下去?

可以这么说,延迟是造成不一致问题的主要原因。如果延迟都为0(即A玩家作出行动的同时B玩家就能看到),那么也就不存在不一致的问题了,就像在真实世界中一样。而同步机制除了基本的通信作用外,最重要的任务就是解决不一致问题,即保证游戏的一致性。同步机制有许多种,根据游戏类型、技术条件甚至时代背景的不同,选择的同步机制也会不同。

2.分类

游戏的网络同步机制有很多,国外也有这方面的论文,抛开具体实现细节,总体来看可以分为下面几类

  • Peer-to-Peer,在这类方法中,没有服务器,游戏参与者的身份是对等的,依靠参与游戏的玩家电脑自行解决同步问题的,最为典型的就是Lockstep
  • Client-Server,在这类方法中,Server端是绝对的权威,所有计算基本在Server上完成。例如,在游戏中向前移动一步,要等待服务器确认“你向前移动了一步”之后,才可以在客户端上进行这个行为。(延迟较低的时候是察觉不到这个过程的,延迟高时会有明显的卡顿现象)
  • Client-Side Prediction,严格来说这并不是一类方法,而是对第二类方法的改进。试想如果所有的操作都必须在得到服务器的确认,然后才在客户端上进行,在延迟较高时用户体验会非常的差。这时可以把常用一部分计算转移到客户端进行,服务器辅助校正即可。
三、什么是Lockstep

Lockstep最初是军队行进中使用的,后来在19世纪的时候广泛在美国监狱使用,成为那个时期美国监狱的一个标识。就像这样

《游戏中的网络同步机制<一> 帧同步Lockstep》” />    image.png</p><p> <img layer-src=

如果你的jdk版本没有什么问题的话,那么你看到的结果一定也是上面那样,而且无论你运行多少次都是这个结果。大部分编程语言内置库里的随机数都是利用线性同余发生器产生的,如果不指定随机种子(Random Seed),默认以当前系统时间戳作为随机种子。一旦指定了随机种子,那么产生的随机数序列就是确定的。

所以,游戏开始前,参与游戏的玩家电脑协商确定一个随机种子,就可以保证在游戏进行过程中大家产生的随机数序列是相同的,也就可以保证计算结果一致。

例如一个英雄的暴击率为30%,对某个目标持续普攻,如果随机数序列为12 32 90 25,小于等于30判定暴击,大于30判定不暴击,那么每个玩家电脑的计算结果都是暴击 不暴击 不暴击 暴击。(这里只是举例说明原理,游戏中的实现细节不一定是这样)

2.外挂问题

在对战平台打Dota的人都见识过全图挂,而且屡禁不止,那么为什么Warcraft III中会有全图挂,而没有其他游戏中的变态挂(如加强攻击力,瞬间移动等等)呢?为什么无法从根本上杜绝全图挂呢?

前面已经说过了,使用Lockstep同步机制,所有计算都是在本地完成的,每轮turn都必须接收来自其他所有玩家的操作指令才能完成计算,也就是说其他玩家的一举一动你的电脑其实是知道的,只不过没有在你的屏幕上展现出来罢了(被战争迷雾遮挡了)。因此,全图挂只要修改Warcraft III的内存数据,就可以去除战争迷雾,达到开全图的效果。而对战平台不可能改变Lockstep这种同步机制,只能在本地检测是否有其他程序修改Warcraft III的内存数据(就像病毒查杀一样),而外挂程序总有办法绕过检测,所以全图挂总是层出不穷。

而另一方面,恰恰因为Lockstep同步机制,其他比较变态的外挂根本不可能在Warcraft III上存在。比如强化攻击力,我们同样可以利用修改内存的方式将增加自己的攻击力,可以直接秒杀其他任何单位,但是别忘了其他玩家电脑也在同步的进行计算,而我们的攻击力在其他玩家电脑上仍然是不变的,这就造成了状态不一致。前面说过了,Lockstep中出现状态不同步的情况时很容易产生蝴蝶效应,最终崩溃退出。

3.断线重连

这个问题一直被广大玩家诟病,因为其他网游从来没有断线之后连不回去的情况,为什么Warcraft III不支持断线重连呢?

Lockstep同步机制是非常严格的,中途加入游戏是从技术上来讲是非常困难的。首先中途加入的玩家要进行状态同步,而状态同步本身包含的内容太多了,其中包括时间戳、伪随机数序列、所有单位的位置属性信息等等,不是简单的复制粘贴就能同步的。这说起来容易,要具体实现起来没那么简单,而且在局域网中掉线情况并不常见,因此早期暴雪的开发人员可能也就忽略这个问题了。

事实上使用对战平台的人才会经常遇到这个问题,在互联网中,延迟高、掉线的情况时有发生。那么11平台的掉线重连功能是怎么来的呢?个人观点,那并不是真的掉线重连,只是我们的丢包情况比较严重,暂时卡了而已。11平台可能做了一些优化,将其他玩家的操作指令保存起来,等延迟稳定的时候再发送给我们。但由于此时我们电脑所处的turn可能落后了其他玩家,所以此时游戏就会像快放一样赶上其他玩家的进度。如果是真的掉线,如停电、程序崩溃等直接退出的情况,我们是无法重新加入游戏的。

4.Warcraft III是不是使用严格的Lockstep机制?

接上一个问题,如果Warcraft III是严格的Lockstep同步机制,那么一定会出现一人卡、大家都卡的情况,而事实上只有当我们是主机时才会出现这种情况,其他情况下我们延迟高甚至掉线都不影响其他玩家的操作。

因此,Lockstep实际是一种理想的模型,如果在实际中使用会造成非常差的用户体验。那么Warcraft III使用的到底是什么同步机制呢?参考What every programmer needs to know about game networking这篇文章后面一个评论的说法

TOADCOP
FEBRUARY 10, 2010 AT 9:15 AM
btw afaik StarCraft don’t use peer-to-peer it uses client-server model with lockstep (at least warcraft 3 does so). It has the advantage what theoreticaly laggers will not affect gameplay/response latency at all (but to not let them fall behind server do timeouts so the lagger can catch up, also doing temporary local game speed increasing) and imo it’s the only and true way to do sync in RTS like games. (and for some reasons this technic isn’t good covered in the web)

然后是作者的回复

GLENN FIEDLER
FEBRUARY 10, 2010 AT 10:20 AM
You are correct. Also something cool is that in a C/S RTS model the server could also theoretically arbitrate to ignore turns from lagging players, and kick them if they don’t catch up – removing various exploits where you can time-shift your packets and lag out other players.

也就是说Warcraft III使用的是基于Client-Server的Lockstep模型。这就是为什么Warcraft III中有主机这个概念,当然这里主机的作用并不是完成所有计算。

(以下为个人观点)
Warcraft III中的主机的主要功能是广播并设置timeout,也就是说在每个turn内,游戏玩家并非直接将自己的操作指令广播给其他玩家,而是先发送给主机,由主机负责广播,且每个turn都有timeout,如果超过了timeout仍然没有收到某个掉线玩家的操作指令,则忽略该玩家在该turn的行为,即认定他什么都没有做,并与其他延迟正常的玩家同步进入下一个turn。而当掉线玩家网络恢复时,主机会将之前保存的turn中操作指令集合发送给该名玩家,而该名玩家为了赶上进度,就会出现游戏快放的情况。

所以Warcraft III中只有在主机延迟高或掉线时,其他玩家才会受影响,否则不受影响。在局域网中,如果主机是正常退出的,那么会选定另一玩家电脑作为主机,如果是崩溃退出的,则所有人都会直接掉线。至于在对战平台上是否有优化就不太清楚了。

五、总结

Lockstep是出现较早的一种同步机制,不过现在很多RTS游戏中依然能够看到它的影子,当然都对它进行了一定程度的改进。

国内关于游戏编程和网络同步的教材、文献寥寥无几,不知道是文化因素还是什么其他原因,难道与游戏相关的技术都是玩物丧志、不学无术?

在我查询资料的过程中,发现国外不仅有游戏编程和网络同步的理论教材,还有大学开设的游戏课程,甚至还有硕士论文是关于设计一个MMORPG游戏的……看看国外繁荣的游戏(使命召唤、刺客信条、魔兽世界),再看看国内繁荣的游戏市场(页游?手游?),看看国外知名的游戏公司(Blizzard、EA、UBISOFT),再看看国内知名的游戏公司(……企鹅?)

这里不是想黑什么,而是觉得计算机作为一门多样化的学科,我们不能固步自封,排斥其中的一些东西。有人说研究游戏有什么用?真的没用吗?看看下面这些应用

  • 网络游戏中广泛应用的航位推测法(Dead Reckoning)美国军方也在使用
  • 游戏中的自动寻路算法,在机器人和自动驾驶中也有应用
  • 游戏中的决策与博弈论也有关联
  • 游戏服务器集群之间的负载均衡与一致性,和现在热门的大数据息息相关

虽然不一定是由游戏本身推动的,但是这些研究之间是相辅相成的,不会做无用功的,何况游戏本身就是增加GDP的一个好手段╮( ̄▽ ̄)╭

    原文作者:懒皮
    原文地址: https://www.jianshu.com/p/64b3f162dcf4
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞