« 开发笔记(18) : 读写锁与线程安全 | 返回首页 | 杂记 »

开发笔记(19) : 怪物行走控制

这段时间项目进展还算顺利,叮当同学在盯项目进度,我专心解决程序上的各种小问题。

最近我在协助解决 NPC (包括地图上的怪物)的行为控制以及 AI 的问题。

目前,我们的进度还处在玩家可以通过客户端登陆到服务器,可以在场景上漫游,以及做一些简单的战斗和技能动作的阶段。按最初的设计原则,我们的每个玩家是在服务器上有一个独立的 agent 服务的。目前写到现在,和中间想过的一些实现方法有些差异,但大体上还是按这个思路进行的。 关键是在于去除大部分的回调方式的异步调用;编写的控制流程自然完整,不需要太多的去考虑 agent 行为之外的交互性。

如果丝毫不考虑性能问题,我很想把每单个怪物和 NPC 都放在独立服务中。但是估算后,觉得不太现实。在 这一篇 的最后一段已经提过这个问题了。

今天展开来谈谈我的方案。

我想把怪物的移动行为独立出来做,以减少 AI 的压力。也就是说,地图上所有的怪,在设定的时候,都可以设定他们的巡逻路径,或是仅仅站立不动。我希望在没有外力干扰的时候,处理这些行为对系统压力最小。

我不想让怪在没有任何玩家看见的时候就让它静止不动,因为这样可能会增加实现的复杂性,并在怪物行为较为复杂时,无法贯彻策划的意图。

最好的方法还是把之隔离,使其对系统的负荷受控。同时也可以通过分离,减小实现的复杂性。

这个子系统是这样的:

它可以接收请求,在单张地图上创建出怪物来。它只关心怪物的坐标。通过 ShareDB 和别的服务分享怪物的坐标。因为它只关心和修改怪物的坐标字段,所以适用于任何结构不同的怪物。

在创建出怪物对象后,可以接受指令,给怪物附加上一个行为。这个行为目前可以是静止,巡逻,跟随别的对象。

这个子系统以一个较低的频率(比如一秒一次),按行为去重新计算所有对象的位置。更新位置后,通过 组播服务 通知地图上所有的玩家 agent 。


这个子系统如何和主系统协作呢?

这里所谓主系统就是地图服务器。我们会把怪物的 AI 模块加载进去运行。怪物 AI 模块会由玩家的 agent 去被动驱动。就是说,如果没有 agent 触发 AI 的处理流程,AI 是死的,不占用 CPU 时间的。每个怪物在生成时,同时通知上述子系统构建一个对象,使它可以在地图中游荡。

怪物由子系统驱动游荡时,通过 AOI 子系统,有可能引发相关的处理逻辑。(一般是进入 agent 的视野,进而触发怪物的 AI 处理)

当怪物 AI 模块接管怪物的控制后,通知子系统删除对应对象,然后进入 AI 控制环节。


这个子系统可以分处于独立进程,独立 CPU 中,并且可以调节控制频率。所以我们可以把这些游荡怪物对系统的负载影响减轻到最小。让系统负荷仅和地图上玩家数量正相关。

对于复杂的怪物逻辑,比如副本中的 BOSS 还是可以以 agent 等价的形式放在一个独立的服务中去处理,这和上面的系统并无矛盾。

Comments

个人感觉1s的情况更新坐标应该会有一些误差,感受没有那么灵敏,而且npc的AI如果都写到AI server上的话,对world server 的压力会小很多,虽然涉及很多同步,但是还是性价比很高,节省出来的性能能使world server 能够支持更多玩家,对网游来说是很有利的事情

之前曾按云风大侠的思路做过一些尝试,把Monster的实现逻辑全部独立到一个AI服上,后续引发的一连串问题如大家所提的那样:
1. AI服必须保留一份和主逻辑服相同的地图数据文件,以供Monster寻路。
2. 进程间通讯增加,各种AI协议,各种AI到Logic的同步数据,各种数据转发。
3. 因为当时测试的数据量不多,所以没有出现明显的Monster迟钝问题,不过不晓得数据量超大之后会怎样,增加新服=增加成本。。
4. 后期维护的各种问题。。
想来还是自己能力不足。AI仅控制Monster移动看来是个可行方案,但追踪动作难免要实时同步追踪角色的位置,如果再牵扯到动态障碍,哎。。 又是各种同步包。。

好东西。 学习学习。

单独的ai服务器和场景服务器的通讯压力会很大,而且怪物的反映会有延时,处理起来也需要写异步代码,总而言之,弊大于利

请问用的是什么引擎啊?开发语言是C++吗?

还有,玩家的角色数据需要维护2份,这个........犯2了

To F22:
好吧,仔细想了想,确实有不妥,本来期望让客户端维护2条连接将ai server和world server完全隔离,减轻world server的消息处理压力,可是我忽略了一个很重要的系统,战斗系统,如果这样完全隔离ai和world,就完全把战斗计算和各种战斗数据同步压力抛给了ai server
关于客户端维护2条socket连接的问题,个人觉得这个无所谓,我不大清楚客户端多维护一组加解密通讯对客户端的通讯效率会造成多大程度的影响,应该不会太大吧,这样不会太大吧,觉得

To F22:
好吧,仔细想了想,确实有不妥,本来期望让客户端维护2条连接将ai server和world server完全隔离,减轻world server的消息处理压力,可是我忽略了一个很重要的系统,战斗系统,如果这样完全隔离ai和world,就完全把战斗计算和各种战斗数据同步压力抛给了ai server
关于客户端维护2条socket连接的问题,个人觉得这个无所谓,我不大清楚客户端多维护一组加解密通讯对客户端的通讯效率会造成多大程度的影响,应该不会太大吧,这样不会太大吧,觉得

client连接ai server?还要另外一组加密通讯来保证?连接会不会太多了,通过world server转发不就好了。ai server本来就要作用于world server,就是直接作用于npc,那直接world server通知client不就好了。

To F21:
客户端还要维持与ai server的连接?难道又要维持一套与ai server之间的加密通讯?客户端与ai server之间还是最好通过 world server来转发进行吧,另外,如果ai server会作用于world server,那么world server把作用后的结果同步给client不就好了。

关于独立ai系统的问题突然冒出这样的一个想法:
让client和服务器系统之间维护两条socket连接
client <-> world server
client <-> ai server

ai server和client之间:
ai server向client实时同步怪物的行为和坐标,client也向ai server实时同步玩家的行为和坐标以供ai系统触发各种ai事件

client和world server之间:
client向world server同步玩家位置,然后做玩家之间的场景数据同步与交互

至于ai server是否需要向world server同步怪物的消息,好像不需要了,甚至感觉ai server和world server之间连接都不需要了

这样是不是将ai独立得更彻底一些?
但又总觉得哪里点不妥,不妥在哪儿,我也想不明白

蛋疼,为毛每次一发表就是多条?

To F10:
个人观点:独立出来的ai系统当然要计算寻路逻辑,跟游戏客户端寻路一样,独立出的ai系统中会有一份跟服务器地图一样的地图二进制文件,跟客户端不同的是客户端由玩家控制寻路目标,ai寻路的目标点由ai系统控制或者事件触发,ai寻路其实是服务器逻辑中消耗比较大的一个部分,是独立ai server的一个比较大的原因

To F10:
个人观点:独立出来的ai系统当然要计算寻路逻辑,跟游戏客户端寻路一样,独立出的ai系统中会有一份跟服务器地图一样的地图二进制文件,跟客户端不同的是客户端由玩家控制寻路目标,ai寻路的目标点由ai系统控制或者事件触发,ai寻路其实是服务器逻辑中消耗比较大的一个部分,是独立到ai server的一个比较大的原因

更新位置后,通过 组播服务 通知地图上所有的玩家 agent 。
你的地图是按什么划分的,是天下2那种无边界的大地图?那么穿越边界的时候,是否通知原来地图的玩家。我感觉是应该作用到npc上,npc再考虑作用到aoi范围内的玩家上。

将ai系统从游戏世界服务器里独立出来确实更利于ai的管理和或扩展,游戏世界服务器只负责场景同步和creature之间的交互逻辑,这样其实更真实的模拟了游戏世界内怪物和玩家之间的关系,但是有一个问题,这样做毫无疑问的增加了服务器Message处理的压力,而且是大大增加了,即便ai server和world server之间是内网传输message,但仍然是不小的压力(分布式设计的纯副本类游戏可能不用考虑这个问题,大不了控制单台物理机上的副本数量),求大大指点一下你们是怎么解决这个问题的.

这个真不懂~~

学习了,最近也在研究这方面的东西

很好,学习了!

话说,有招系统运维攻程师的计划么

AI需要大量与周围NPC和玩家的交互,不在一个服务器上,设计复杂的BOSS时会有很多麻烦

路过一看

请问云风大侠,

这个子系统以一个较低的频率(比如一秒一次),按行为去重新计算所有对象的位置。”

在计算怪物位置时,是否有考虑服务器端的寻路操作,如避开地图中的各种路障,求指点大体思路。

如果是通过你所说的sharedb的话,在实现上如果使用进程间共享内存,就算不涉及到加锁,感觉上还是够慢的。

"这个子系统可以分处于独立进程,独立 CPU 中" AI中如何取得其他agent(玩家)的信息,例如查找周围的玩家?

当年我们的实现方案也是怪物和玩家完全等同对待,都是一个agent去处理,只是某些逻辑实现上有偏差。
移动,计算坐标,其实是一个很耗cpu的行为,(特别是我们的游戏移动处理很特别)。当时做法就是把移动独立出来,作为一个单独的服务。

期待好游戏的诞生,至少不能比diablo3差吧,哈哈

把每单个怪物和 NPC 都放在独立服务中。确实是相当棒的想法,这样怪物就可以理解为执行脚本的机器人玩家了,整体逻辑流程就完全一致了。
请问这种实现的内存压力大概有多少??

很赞的解决方案啊,也省了未来再去优化。回2楼我觉得国内更多的是些很浮躁的团队。。

项目进展半年多了,才这个进度,这团队不行啊.
国内这种水平的团队的一抓一大把了.不是几前年了.

不懂

Post a comment

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