以下的讨论,建立在这样一个网络结构假设的基础上:玩家各自控制一台机器,叫客户端,它们连接到共同的服务器(组),并且通过该服务器(组)来完成同步。当然,在理论上,这个假设未必成立,因为没有任何法律上的限制禁止我们将网络游戏建立在P2P的网络结构上,不过到目前为止,似乎还没有这么做的,所以我们在本文讨论中直接排除了这种结构。(也许P2P游戏会成为游戏网络的未来架构,谁知道呢)
在这样的网络结构前提下,我们可以合理地认为服务器将承担场景同步和消息广播的任务。
再论同步什么
在继续往下写之前,关于同步什么的问题,还有一些需要交代的。
前面我们讲过,需要同步的,是玩家视野范围内,某些物件某些属性的改变。这个在实际操作的过程之中,会有小小麻烦。比如,一个PC说了一句话,这句话应该被10米之内的其它玩家听到。那么,这句话算是什么东西?如果说它是属性的话,就会使PC的属性列表显得怪异,等于是PC的话语列表属性中增加了一个值,而这句话在播放完成之后又要从列表中删除。(当然,有一个办法是给每一句话打上一个时间戳,即使如此也需要有时机晴空话语列表中的过时记录以免玩家负载过重。一直背着一个话语列表行走,还是很辛苦的:) 另一个办法是将一句话设计成一个物件。当一个玩家讲了一句话时,玩家属性并未发生改变,但是场景中增加了一个话语物件,这个物件在播放完自己之后,自己消失。无论将这句话设计成一个物件还是一个属性,都会使得处理显得突兀,不自然。自然的办法,当然是广播一个事件,这一事件表明,有一个玩家在说话,而在这个事件属性中携带着一句话。
这使得我们可以用另一种更自然的方式来描述同步什么的问题:
需要同步的,是玩家视野范围内,某些物件发生的某些事件。
因为属性的改变肯定可以被认为是由于发生了某些事件的结果(当然属性改变本身就可以被当成事件),而一个事件的发生也可以被设计成不改变任何物件的任何属性(比如某人说了话,或者做了一个不影响其位置的动作)。这样,在处理上,使用事件比使用属性改变来得更加灵活。
同样的道理,我们可以为事件定义LoD,来加以消息过滤。
如何同步
再回到如何同步的问题。让服务器来承担信息同步的任务,简化了策略的规划,但是还是存在多种可能性。比如说,同步命令的发起和权威性,可以采用谁发起谁提供的策略,也可以采用由服务器集中控制的策略。又比如说,广播范围的确定,可以采用谁发起谁确定的策略,也可以采用由服务器集中控制的策略。具体采用什么模式,取决于不同的设计方法。在某一种模式下,可能是玩家生成事件,同时确定该事件需要向谁广播,然后通过服务器广播。在另一种模式下,可能是玩家生成事件,但是由服务器来确定广播列表然后进行广播。
这里面有一些有趣的细节需要考虑,从而可以设计出多种同步模式。无论在哪一种模式下,都需要考虑网络的延时,以及在信息失同步的情况下如何再次同步的问题。笔者在这里描述的一个同步策略,是自己在游戏设计中准备采用的模式。它的基本思路如下:
任何事件的最终确认,发起广播,确定广播列表,以及在失同步状态的的权威性,均由服务器提供。
出发点
这种模式设计的出发点有三个:
- 为了防止游戏外挂程序篡改游戏数据,所有的事件和消息必须经由服务器发起或最终确认才是有效的
- 由服务器集中控制的同步机制,减少了网络延时对场景在不同客户端之间同步的影响。在这种模式下,不同客户端之间的差异取决于两者与服务器之间网络延时的差值,而不是相加。
- 集中控制的策略使设计和调试变得简单。场景的录制和回放将更加易于实现。
......
