手游slg寻路是如何实现的(一)

2,232 阅读4分钟

超大型地图寻路在服务器上的实现

寻路算法一般是应用于前端的开发中。算法本身是一个CPU密集的工作,同时也兼具内存密集的特点,在SLG类型的游戏中,尤其是率土like类型的超大地图,要实现这个需求,是一个很有挑战的工作。以下聊的种种是在一个企鹅平台上线的大型slg项目中的具体实现。

条件与难点

游戏本身是SLG手游,率土like,出兵抢地地,赛季合服玩法,每个区服数据独立,能够支持10000+同时在线。

整个游戏世界的地图是一个250万个连续的六边形网格,纯静态地图数据有70M。地理上分为州,郡,县,区域被边界障碍包裹(这很重要)。地表数据有障碍(山,水),区域连接的关卡,码头等。

要支持动态数据寻路。玩法中,玩家主城,要塞等特殊建筑阻止通行,并且有关联关系(同公会的玩家可以通行,中立或者敌对关系不可以),中立城池也有归属关联关系,比如地图上码头只有被本公会占领后方可通过。

玩家的寻路请求有一定频率。玩家在浏览地图时,每当选中一块地格时,需要显示出所有可出兵地点的行军线路。如果部队分散到多个要塞,则需要每个要塞到选中点的行军路线。也就是说玩家点击一个格子,会有多个寻路请求就发出。当部队到达地点后,会有自动寻路返回需求(比如目的地被其他玩家抢先一步,或者本人家打败了主将落荒而逃)。都需要一定实时响应速度。

如果玩家找到地图千里之外,无意识的选中查看一个城池,那么就需要显示出部队翻山越岭,穿关卡,过码头,出郡县,跨大洲,到达此地的一条最佳寻路路径。每个出兵地点一条线路。

寻路路径为格子相连,整体尽量走直线(六边形6方向连接,到下一个格子的距离相等),表现出来的效果是走折线。要求最佳原则,路径最短(部队行军速度固定)。整体表现如下

行军路线.jpg

当回看上边的各条要求的时候,每个都让心中涌出一句,服务器实现不了,后端臣妾做不到,全服玩家同时寻路服务器扛不住的,寻路应该前端做的,等等各种撕逼语言。但实际上整个开发过程是一步一步迭代出来的。最终在一定的条件下,最终实现上述的所有需求。

问题拆解

抛开情绪,理智分析。

前端实现还是后端实现?

考虑过前端实现后端校验的思路。但是从需求上来看,在远距离寻路时,需要整个地图的动态数据,因为路线是未知的。如果强行让客户端维护动态,又涉及到维护和同步的问题。客户端的内存占用,CPU消耗,手机发热也是很大问题。那么近距离客户端自己算,远距离后端算呢?还是数据的问题,整体地图是完整的一块,不存在私有地图。自家主城附近的同样会被其他玩家打掉,这时候计算时,就需要其他玩家的数据,公会关系数据等等。

最后,明确是服务器做全地图寻路

开发要点

  • 六边形折线寻路
  • 跨区域路线拼接
  • 动态寻路的数据维护
  • 后端寻路策略的优化

选择了一个大致正确的方向,就出发了。至于性能问题,响应速度,服务器承载,动态数据更新,甚至内存占用等等问题,都是在开发过程中一个个具体暴露出来的时候,然后又一个个解决掉。整个模块开发的过程,是一个时间紧迫,又旷日持久,或动辄服务器瘫痪,或前端表现诡异,与各种bug斗争的过程。

最后做到的效果如下:

  • 一组服务器1万人同时在线压测,2000人打地(近距离寻路),2000人(远距离寻路,中间会有打断行军,回城重新寻路),服务器每秒处理200+的远距离寻路(必须限速,跑赢了竞品的数据),客户端登陆测试,游戏体验流畅,远距离寻路响应速度秒级别。

后边会描写在服务器上写“A*”寻路的详细心路历程的。