大地图动态阻挡与寻路的一种解决方案

从坦克大战的砖墙到星际2中哨兵的力场,动态阻挡作为地图或关卡中的重要元素,在游戏开发中可以说是屡见不鲜。


力场.png

不过由于算力和内存的限制,往往只能在单机游戏或一些地图偏小可以通过gridmap方式描述地图的游戏(如RTS、MOBA)中实现。
而对于MMORPG或者沙盘类的SLG游戏,情况则会复杂很多。
1.由于这类游戏的地图往往很大,用gridmap内存开销会很夸张(试想一下开一个1w * 1w的数组)。并且就算内存可以承受,基于这种规模的gridmap的a*搜索也几乎无法在有效搜索深度内给出可行解。
2.由于是大量玩家同时在线,无法仅加载地图的某一个部分(对MMO来说往往还需要同时加载多张地图)。而且需要保证不同玩家看到的移动行为基本一致,这就要求服务器和客户端之间的逻辑处理的一致性,很难通过纯客户端的一些trick的方法来实现效果

大地图的一般性寻路的解决方案:导航网格(更完整的介绍可以参考之前的专题
核心思路就是尽可能的将地图中互相之间直线可达的区域合并为同一个凸边形,最后将地图处理成由若干个凸多边形构成的联通区域。在这个抽象出来的凸多边形集合上进行a*搜索,结点数量将会比直接用gridmap少非常多。

在RecastNavigation中,其实给出了一套处理动态阻挡的解决方案,核心思路是
1.将地图划分成若干网格状的tile(tile的尺寸比grid要大很多,比如grid是1 * 1的小格子,而tile往往是100 * 100或者更大尺寸的大网格)
2.以tile为单位,每个tile独立生产导航网格,然后再处理相邻tile之间的连通性
3.当加入或移除一个动态阻挡时,判断该阻挡与那些tile相交,然后重算这些相交的tile的导航网格,其他tile不处理。

这种方案可以满足一定的业务需求(比如哨兵的力场用这种方案应该很容易解决),但也有一些局限性:
1.重算导航网格的计算量远比gridmap修改标记位要复杂,虽然以tile为单位减小了影响的范围,但对于MMO或SLG这类有大量玩家同时在线操作的游戏来说,还是会成为计算瓶颈
2.动态阻挡的形状是提前定制的(比如标准的立方体、圆柱体),因为这种标准的凸多面体(多边形)计算相交的tile会比较容易。而想要支持更一般的形状的阻挡则比较困难
3.阻挡的尺寸不能小于体素块的尺寸,而对于规模比较大的地图来说,体素块尺寸也无法做的很小(比如8000 * 8000的地图,如果使用1 * 1 * 1的体素,在生成导航网格阶段内存可能直接就爆了)。加入你的游戏中需要有很薄的墙,就需要考虑清楚能不能在这种尺寸下生产导航网格。

笔者在实际的开发过程中针对不同的业务需求采用了一些方法来绕过上述这些局限性

需求情境1:

关隘类玩法(代表游戏《万国觉醒》)
沙盘地图被划分成9块独立的区域,区域内部可以自由行军,但区域之间的行军路线必须通过连接两块区域的关隘
并且如果关隘没有被占领,则无法通行


万国.png

关隘.png
解决方案:

0.预处理:
a.不同区域之间在导航网格层面不联通,相同区域内部联通
b.每个关隘抽象为一对连接点,这对连接点记录了它们关联的两个相邻区域,它们之间的路径就是点到点的线段
c.属于同一片区域内部的连接点,根据按导航网格与计算出它们的联通路径。
此时所有相邻的点对之间的路径已经计算完毕
1.寻路分两层:
a.第一层首先判断起点和终点是否在同一片区域内,如果是则直接按导航网格寻路
b.如果是两个不同的区域,则枚举起始区域的所有被占领关隘的连接点和终点区域的所有被占领关隘的连接点,求它们之间的最短路。
c.由于这些连接点之间的直连边长度在预处理阶段已经提前算好,此时的寻路问题已经转换为普通的最短路问题,直接上prime算法即可


区域.png
需求情景2:

桥梁玩法(代表游戏《红警》)
1.桥梁可以被炸毁、修复或占领
2.从河岸的一边移动到另一边不一定要经过桥梁(如果有更近的路,或者桥被炸毁也可以绕远路)
3.桥梁可以出现在地图的任意位置。
乍一看桥梁和关隘似乎差不多,但上面关隘的解决方案的前提是关隘只存在于不同区域的连接处,区域内部是保证联通的,而跨过区域的寻路必须经过关隘。在桥梁的情境中,它只是被当作一般性寻路时的备选项之一。
解决方案:
在RescastNavigation中提供了标签机制,可以在体素化阶段对指定范围的体素块进行标记,进而在最后生成的可行走面中,保存下这份标记值。
在a*搜索阶段,针对当前搜索到的可行走面(搜索结点),添加一个过滤函数,除了需要满足联通性之外,还需要满足过滤条件
在桥梁问题中,可以记录下寻路实体所占领的所有桥梁id,让后判断当前行走面记录的id是否在占领列表中,如果不在,则剔除这一块可行走面

需求情境3:

玩家可以在大地图上进行DIY建造建筑、围墙等,这些建筑会对地形产生影响,部队必须绕过这些建筑行军
从玩法和技术实现层面两个角度思考之后,我们对这样的DIY加了一些限制条件:
1.建造范围必须在玩家主城的一定范围内
2.多个玩家之间不能完全把路堵死
针对这两个条件,我们最后修改了建造规则:
1.每个玩家有一个圆形的建造范围圈
2.不同玩家的建造圈直接不能重叠(实际上相切也不行,有至少1个单位的外围宽度)

解决方案:
1.由于保证了不会完全把路堵死,所以地图上两点之间的连通性实际上没有变化(即如果原本通过导航网格可以寻路的点,在建造之后依然可以通行,只不过路径需要修正)
2.我们首先按导航网格算出一条初始路径。如果这条路径没有与任何主城圈相交,则可以直接作为最终的寻路路径
3.如果与主城圈发生了相交,则将相交的这一段线段替换为绕着主城圈的一段圆弧(保证路径不经过圈内部),当然相交可能不止一处,每一处按相同方式处理即可
4.当寻路的起始点和目标点在主城建造圈内部时,需要再进行特殊处理:
a.由于建造圈的范围一般在50 * 50以内,这时候gridmap就有用武之地了。
b.以主城所在位置为中心,为每个主城维护一个50 * 50的gridmap,当建造、移动、拆除建筑时,对该对应的gridmap的数据
c.当寻路中包含“出城”或“入城”时,将这一段路径单独拆分出来,通过针对gridmap的a*寻路计算路径,再拼接上剩余路径
5.到目前为止只是一条预算的路径,仅仅可以保证可达性,但绕行的行为不能保证是实际最优的。所以在每一次的坐标更新tick中,再判断一下当前移动中的物体是不是又走到的一个新的主城圈范围附近。当第一次走到新主城圈附件时,会立即触发一次重算,将剩余路径拆分成城内gridmap的a *+剩余部分的导航网格计算


修正.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容