由于分区计算,所以相邻区之间的冲突问题解决是很关键的,不论是静态分区,还是动态分区。边界冲突的核心是由于分区引起的。当一个逻辑上独立的实体跨在分区的边界上,那么,从分区的理论上,就会导致该实体被硬性的分割为2个实体。其中一个分区为计算该实体的行为时,比如走动,那么他就必须同时获取另外一个分区中,该实体的状态;而另外一个分区遇到的也是同样的问题,这就是产生了边界冲突。表现的连续性要求和实现的分区技术是边界冲突的关键因素 。
现在,我们先建立个简单的模型来讨论这个问题。假设存在A、B两个分区,有个角色R沿着边界线行走。这个模型很简单,但同样能反应大多数问题。假设A负责计算R的状态,当R从x1y1移动到x2y2,那么A就必须获取R在B中的状态,比如他的走路位置,速度等,同时,还需要知道B区中的地面情况。因为R并不知道他正在走的路是被分割成2个区,所以他有可能在他走的路上左右摇摆成S形,那么A和B所拥有的R的数据将剧烈抖动,一会儿A区剩下右脚趾,一会儿B区剩下左手掌,这种情况很可怕。为了避免这个剧烈抖动所造成的影响,我们必须将R作为一个整体保存在A区,那么因为R剧烈摇摆造成的抖动将被大大降低了。为了降低分区造成的抖动,我们在分区时,加入逻辑为单位的限制,也就是说逻辑上完全独立的实体,不能被分割。于是,我们只要在A区中计算R的状态,然后刷新到B区中,因为边界造成的冲突就不复存在了,AB既能保持一致,也能保证分区的存在。
事情并没有完,如果R1、R2正好在边界上战斗,那么事情就严重了。R1在A区,而R2在B区,显然,这种原则同样满足前面的原则,但关联的实体R1、R2依然造成很大的麻烦。当R1攻击R2时,R1的状态依赖于R2,而R2的状态同样依赖于R1,R1和R2之间的碰撞检测同时依赖于双方的状态。显然R1、R2分置于不同的区给这种关联计算带来了复杂度。但是,将R2移到R1中,却也同样不行,为什么呢?假设R1是个法师,他有45码的攻击距离,那么,就必须将这45码距离内的所有实体都移入到A区,再假设还有个NPC同样在45码的距离外攻击R2,那么,就是90码距离内的实体同时移到A区中,这显然打破了分区的要素。
更可怕的是,如果有个国战在这边界发生,那么R1...Rn可能分属于N个分区。巨人网络在《征途》中宣称支持万人国战,我不知道他的实现技术,不过我猜测他应该具有某个限制,比如在某个区域内发生,然后将这个区域置于一个服务器或者服务器集群上。但不管怎么说,国战在分区策略中造成边界冲突将是可怕的。
然而,我们研究下,发现造成这种严重后果的原因有几点:
1、实体的独立性和实现的分割。每个角色是独立的,但分区却可能将他们分割成多个计算单元。
2、实体的关联性和实现的分割。某种动作,比如魔法攻击,将独立的实体关联起来,不过实现的分割导致他们不能同属于一个区。
3、实体的关联性复杂度。当实体关联度比较小时,还能通过计算能力硬扛,不过当关联度增加时,比如国战,一个范围魔法可能覆盖整个军团,几千人,这种复杂度是计算能力难以忍受的。
我们发现,实体的独立性是无法避免的,将一个实体分割放置于多个区,带来的问题将更加复杂。但是关联性和关联度却是可以简化的。我们就拿国战作为例子。
假设2个军团静止不动,那么关联性就不复存在。当一个角色R1发出魔法M,那么源和目标之间关联性就存在,我们将这个关联予以切割,当M在A区运行时,B并不做计算,当M进入B区时,M的计算就转入到B,A区放弃他的计算,直到击中Rx。M本身也成了一个独立的实体,如果M是范围魔法,那么关联就成多个一对一的关联组成,将复杂的关联转化为简单的关联,降低了复杂度。将每个简单关联予以切割,又解决了关联和分区的矛盾。
现在,我们给出一个解决方案。
1、将所有的实体在逻辑上划为成各个最小粒度的独立实体,比如一个角色,或者一把剑。
2、将所有的实体划分为静态和动态实体。其实,所有实体都是动态实体是最好的,但计算量太大了,而且也没有必要,比如说地图。我们将他切割成多个分区,由于是静态的,所以变化就不会太大了。
3、每个实体除了为表现而存在的要素外,还必须有个记录关联的逻辑成员。而关联也将被视为一个逻辑上独立的实体,比如魔法攻击中火球,他是关联攻击者和攻击目标的实体,同时也是逻辑关联。
4、当关联发生时,关联的源或者关联的目标将被切割,而只和关联发生关系。
这个方案会解决了大部分问题,但不是全部,其余留给后续的讨论。
以前玩英雄无敌3时,有个很好奇的地方,就是在编辑地图,效果很好,没有明显的边界存在。比如在一个沙漠中,拖个草地进去,在草地里在扔个水塘进去。显示出来的边界却很圆滑。这个技术很值得学习。后来,我将英雄无敌3的资源给解析出来,才发现更有趣的地方,其实沙漠、草地、水塘有多个不同形状构成,很平滑。这个技术值得学习。