« KISS | 返回首页 | 被 Darcs 折磨了一天 »

把 AOI 的部分独立出来

应该是在 blog 上第 2 次讨论 AOI 的问题了,另外还要算上一篇写完没有公开的。

昨天刚出差回来,晚上跟前大唐的服务器主程聊了一下。扯到了 AOI 的问题,我提了个分离这个模块的方案,在此记录一下。

AOI 主要有两个作用,一个是在服务器上的角色(玩家或 NPC )做出动作时,把消息广播到游戏地理上附近的玩家。当进程中负责的玩家不是很多的时候,可以直接对整个进程内的连接广播。这样的处理最简单,随着硬件的提高,可能是未来的主流方法。但是目前,为了减少处理的数据量,尤其是带宽,我们通常需要 AOI 模块裁减一些数据。

第二,当玩家接近 NPC 时,一旦进入 NPC 的警戒区域,AOI 模块将给 NPC 发送消息通知,以适合做一些 AI 的反应。

AOI 的实现算法很多,这里不展开来谈。我目前关心的是,如果 AOI 在游戏中非常重要(尤其对于即时战斗模式的大场景 MMO )能否把这个模块抽离到独立进程中。

首先我们来看第一个需求。其实在游戏中,需要广播的消息大多次序不敏感。比如移动,是 A 先移动还是 B 先移动并不重要;又比如攻击,是先攻击再移动,还是先移动再攻击也不重要。我指的先后是指 client 接收次序。攻击是否启动虽然跟距离有关,但是发出攻击指令前,服务器逻辑已经校验过合法性。也就是说,服务器发过来的信息都是合法的,client 就不用太在意位置改变在攻击前还是攻击后了。

那么,我们把 AOI 广播的这个职责拆分到独立进程做,就不需要跟逻辑进程协调发包的次序。这是个好消息。

设计一个 AOI 进程,让逻辑进程在任何一个对象改变位置时发一个包通知 AOI 进程,这样等于复制一份对象位置状态在 AOI 进程中。以后,当对象需要广播它的状态变化,只需要把需要广播的消息发到 AOI 进程里,然后由 AOI 进程过滤一下(筛出附近的对象,做一个组播)。

需要注意的是,由于消息都是异步发生。我们在 client 接收对象 id 时,应该过滤掉一些过期的 id 号。因为有可能逻辑服务器已经删除了某对象,但是 AOI 服务器迟一些发送了跟这个对象相关的消息。(把对象删除的消息交给 AOI 服务器转发是一个糟糕的想法,因为这增加了 AOI 服务器的职责,增加了复杂度)

对于 AOI 消息通知的问题,可以让 AOI 服务器在检测到对象侵入别人的警戒区时,向逻辑服务器发会一条消息。这个消息不需要实时反应。比如,策划要求一个 NPC 有 20 米的警戒区,其实不必在玩家刚好 20 米的边界上触发,稍微延迟半秒是无所谓的。而且警戒区越大,允许的延迟时间就越长。

单独的 AOI 服务,可以根据警戒区的半径,进行优先级排序。然后有条不紊的通知消息一个个发回。

对比单独的 AOI 模块,独立 AOI 进程有更低的耦合度。通过协议耦合而不是接口耦合。更容易维护和日后的优化。没有和逻辑部分的共享状态,减少了 bug 滋生的可能。


ps. 最近跟新同事讲了一节课。其实没讲太多技术上的东西。只是介绍了游戏行业,以及计算机行业的硬件发展历程,以及游戏的进化,还有一点点软件开发上的进步。

我想,一切的历史都在见证,只有把东西设计的足够简洁,才能够顺利的向前发展。如果不够简洁,有一天我们会抛弃它们,或者为之付出代价。希望可以给刚从学习毕业的同学们一些启示。

前天开会前抽空读了一小时新运营的大唐二的服务器代码。追查出一个隐藏很深的 bug 。据说这个项目刚对外开放的这几天情况不太好,老是当机。程序员应该明白,其实也不一定是很多 bug ,但是一个就够你受。

大唐 2 的服务器写的挺“精巧”,C++ 和 lua 之间绕来绕去的,差点没把我绕晕。太复杂了……

Comments

我到觉得可以把AOI归并到一个广播服务器里去,有几种不同的广播策略。AOI在2D游戏里就是附近广播或者全场景广播。 AOI广播之外的一点就是要更新附近玩家的列表。 解决了场景问题,网游服务器不会有太多难处了。因为玩家都是在同一个空间下才会有交互。 跨时空的交互,就是SNS的做法了。只需要维护关系和title,其他数据就不需要维护了。
to sjinny :那么这虽然不会有同步问题,但是会增加AOI进程与其他进程的耦合 我觉得刚好相反,如果移动相关的逻辑都进来才会耦合。
这里的AOI 应该是指Area of Interest
感觉sjinny的做法不错,npc太多,大部分时间位置的信息是不需要的,npc可是不停移动的。作为逻辑的一个模块也好,让npc和user主动去获取而不是接受通知,在获取的时候计算,可以减少计算量。
@quick 你好像找错人了,你应该去找策划的麻烦,云风做的都是底层的东西。
麻烦你不要再出害人的游戏,好不好?? 不要老是做那些弱智的游戏好不好??
你好,大家都是搞技术的,可以交流一下。 打了很多次电话到网易,可总找不到人。 对声音处理的原创技术感兴趣吗? 最终的结果是让PC甚至手机能做非特定人的语音识别(大词汇量,高抗扰)。
云风大侠:以后写博时能不能在那些缩写名词后加个全称,如AOI(A.. O.. I..)好让我们定些初学者能看得懂一点点了。。就是看不懂也多记个单词。。谢谢!
keep is simple &stupid
simple is better, small is better. ______________ sign~
AOI进程的职责是什么呢?如果不包括运动管理,而只是根据其他地方发来的静态位置信息做计算,那么这虽然不会有同步问题,但是会增加AOI进程与其他进程的耦合,除非这个计算量非常大,不然我觉得分出单独的进程意义不大。如果AOI进程的职责也包括了运动管理,那么就意味着所有和位置有关的操作都应该放到这个进程里来,或者说应该由这个进程为其他进程提供位置方面的信息,而这信息主要就是不同级别的AOI里的对象列表。所以可以考虑做成一个服务,以固定的频率告知其他进程各个对象AOI内的对象列表。当然并不是所有对象都一直会订阅这个服务:玩家对象会一直订阅这个服务,而对于NPC之类的,只有当一个NPC处于某个玩家的AOI内时才可能需要订阅。 所以我的想法是,把位置的更新和运动的模拟完全内置到这个服务中,AOI内的消息广播之类的从AOI服务拿出来放在外层调用者那里。由外界订阅AOI列表服务。
这几天一直在玩大唐2,游戏不错,很好玩,但是却不得不忍受每隔一段时间,客户端就崩溃一次的情况,游戏也非常卡,问题还没有解决......
有幸回答了16位地址能传送多少位数据这个问题, 首次见到云风:)
simple is better, small is better.

Post a comment

非这个主题相关的留言请到:留言本