同步什么
谈到场景同步,首先碰到同步什么的问题。看官说,废话,场景同步,当然是同步场景。这样说固然没错,但是,这个命题有两个问题。
一是场景里面包含什么信息。二是整个场景的同步会占用巨大的带宽,而且也是不必要的,一个玩家的视野有限,将他看不到的空间中的物件信息同步给他,没有多少意义。
所以,我们首先来搞清楚玩家视野,然后来确定视野中什么信息需要同步。最后再来回答如何同步的问题。
视野
视野的问题没有我们想象的简单,它不简单地等同于玩家视线范围内的那部分空间。视野可以比这个空间大,也可以比它小。当你看着远处的山峦的时候,山虽然在你的视线之内,但是山上的一个怪物,由于距离太远,却是不能被你的目力所及的。反过来说也是一样,当你看着远处的山峦的时候,你背后可能来了一个敌人离你越来越近,你只要一转身就可以和它作战,但是当下它却没有出现在你的视线内,那么它的信息是否需要同步? 在第一人称游戏(也就是说摄像机就是玩家的眼睛)中,玩家所看到的空间有相当大的局限,因为常常察觉不到身后的危险。而在第三人称游戏(摄像机通常在远处跟随玩家)中,控制PC的真实玩家可以看到更多的物件,但是在探索空间的时候却没有第一人称那么自然。无论是第一人称还是第三人称,我们通常都不采用玩家的物理视野来作为玩家视野。有的时候,人们干脆把这个玩家视野不叫视野,而叫AoI,Area of Interest,中文叫做兴趣范围。言下之意就是,每个玩家有个感兴趣的区域,它只需要同步兴趣范围内的物件信息就足够了,因为它反正对其它信息也不感兴趣。
所以,我们虽然勉强还把这个同步区域叫做视野,却要时时记住它和玩家看到的空间不是一回事。
那么,这个区域是怎么界定的呢?通常的做法是以玩家所在的位置为圆心,画一个一定半径的圆(如果是3D游戏里面,一般就是一个圆柱体)。就好像我们所说的方圆×××。为什么要用圆,而不用其它的形状呢?这个问题大家自己琢磨一下就明白了。
半径
问题是,这个半径得多大才合适呢?画大了,增加了多余的同步信息;画小了,玩家可能来不及反应(比如有敌人可以进行远程魔法攻击的)。通常的做法,是取一个比玩家物理目力所及的范围稍稍大一点的一个距离。这样可以对快速移动的物件(尤其是敌对物件)加以缓冲,同时也不导致过多的同步信息冗余。所以,在3D游戏中,可能视野会有个几百米,而在2D游戏中,则一般比屏幕宽度的一半略大。
回到同步什么
视野范围内有许多的实体,有静态的场景物件,这些不需要同步,因为可以事先加载。需要同步的是动态的物件,包括PC,NPC,物品,道具等等。这些物件携带着很多信息,我们管它们叫物件的属性。有些属性,例如物件的位置和方向,是一旦能够被看见就应该是同步的,因为位置和方向决定了物件的方位和运动趋势,而这是玩家和它们进行交互的基础。另外一些属性,如其它PC身上的装备,可以在距离足够近的时候才进行同步。还有一些物件,比如其它PC在视野内作战时所产生的技能光效,也可以进行灵活处理,比如在一定范围内可见等等。
为了处理这种灵活性,最大限度将带宽分配于必要的物件和属性同步,我们在设计上可以引入LoD概念。这个缩写在游戏编程领域经常会见到,它是Level of Detail的缩写,中文叫细节级别。它的基础概念很简单,就是说一个人在真实世界中观察空间时,越近距离的物件看到的细节越多,越远细节就越不清晰。这意味着相同的物件,它们的细节级别是随着它们和观察者之间的距离而改变的(当然,也可以争辩说和观察者的视力也有关系,但是作为计算机处理而言,没理由让某些计算机近视一些)。在一个给定的距离和细节级别下,物件的低LoD属性是可见的,比如轮廓什么的,而高细LoD属性就是不可见的,比如脸上的一颗痣。另一种可能是,物件本身很小,当距离达到一定程度的时候,虽然它还在视野之内,但是已经不可见了。这样,通过LoD的设计,我们可以过滤很大一部分不必要的属性同步,从而节省同步的带宽,提高同步的效率。
可以为物件和物件属性分别分配LoD值,由于LoD值与距离直接相关,可以直接使用距离单位来标识LoD。比如说,一个掉落物品的LoD是30米,这意味着它的同步信息仅需要广播给以它为中心方圆30米内的玩家进行同步。再比如说,另一个玩家的头盔属性的LoD是100米,这意味着它这个头盔属性仅需要在它距离某玩家100米以内时向玩家同步。通过LoD对物件及其属性进行过滤,我们基本确定了同步什么的问题:
需要同步的是 玩家视野范围内的 某些物件的 某些属性的 改变(属性对玩家而言没有发生变化时不必同步的)。
下一讲
终于要讲同步的具体策略了......
