通用游戏地图解决方案设计解析
创始人
2024-05-28 18:57:42
0

前言:

在软件开发过程中,我们都希望能设计出一个稳健的,可维护的系统,为了实现这个目的,人们总结出了很多相关的设计原则,比如SOLID原则, KISS原则等等。SOLID每个字母代表了一种设计原则,具体大家可以去看《架构整洁之道》这本书或者在网上找相关的博客学习。在本系统中将应用这些原则,力求得到一个可用好用可理解可改动的通用地图模块。SOLID原则中的D,指的是Dependence Inversion Principle,中文可以叫依赖倒置原则或者依赖反转原则。其强调的是在处理依赖关系时,应当尽可能依赖抽象类型,而不是具体实现。 在绝大多数情况下,抽象的东西是稳定的,在设计这个抽象类或者接口时,我们往往会带着前瞻性的思维去考虑,这个接口设计得是否合理?是否方便使用者去实现去拓展?如果一个抽象的对象发生变化了,那对应的所有实现一定会发生改变,而如果具体实现发生变更,不会影响到抽象接口。因此我们有理由判定,接口是不太容易变更的,如果一个接口被反复修改,那一定是设计这个接口的时候有地方不合理:接口承担的内容过多;或者是接口方法不够通用,带进来了一些业务相关的东西。依赖反转原则也是本文主要讨论的原则。

正文

结构组成

本系统主要由三部分内容组成,一个是基础的数据结构模块,一个是寻路模块,一个是地图模块。三个模块功能内聚,但也存在耦合,为了防止一个模块修改导致其他模块发生变更,所以在耦合时,尽量使其仅依赖其他模块中的接口,因此模块具体实现修改并不会导致其他模块受到影响。下面将简单介绍这三个模块的内容与设计思路。

数据结构模块

基础的数据结构模块提供了一个最小堆和最大堆,这是具体的实现,其目的是为寻路模块提供服务的,寻路模块直接依赖了数据结构模块,如果从设计的角度出发,这其实是不应该的,因为前面说了我们要依赖抽象类或接口,而不是具体实现,不过我们也可以发现,最小堆和最大堆相对来说是一个较稳定的东西,其设计完成一旦通过验证,就不太会有理由再去修改它们,因此可以认为这个虽然是具体实现,但是是一个不容易发生变更的具体实现,所以直接依赖这个具体实现也是没问题的。如果非常希望解除耦合将这个直接依赖给取消掉,我们也可以考虑引入一个IHeap的接口,让寻路模块依赖这个接口,同时原来的最小堆最大堆实现该接口,因此寻路依赖堆实现类,变成了寻路和堆实现类均依赖IHeap接口。

原依赖关系

image-20230303132941756

新依赖关系

image-20230303133036132

寻路模块

寻路模块中定义了一个寻路的接口IPathSearch,并实现了三种A星算法,分别是原始的A星算法和两种经过一定优化后的A星算法,实现这个接口的好处在于,如果后期我们需要针对特定的场景比如横冲技能,使用额外的寻路规则,仅需额外再实现一种新的寻路算法,并在原本实例化寻路算法的地方改成实例化新的寻路算法即可,而使用的地方由于依赖的是IPathSearch接口,因此完全不需要做任何修改。
PathFinding类图.drawio

地图模块

地图模块主要分成地图抽象层、地图具体实现和地图生成三个部分,具体可查看文章后面的类图或项目代码。

地图抽象层定义了整个地图模块的基本要素和必要方法,比如IMapGrid接口定义了地图的基本数据,对外的方法等等。该接口依赖INode接口,INode接口定义了一个最基础的地图节点是啥样的,而IPathNode则在INode的基础上,增加了寻路相关的属性。另外定义了一个IMapShow的接口,负责处理地图节点的实际显示,比如绑定地图数据层和实际节点对象等功能。INodeEntity定义了节点的基本操作,比如设置高亮等等。在这个层中定义的接口,均不依赖某个具体实现,但定义了地图的几乎所有行为,在实现功能的前提下保证了该层的稳定性。

地图具体实现则实现了两种常见的游戏地图:网格地图和六边形地图。这两种地图实现了IMapGrid的方法,并在实例化的地方注入了创建节点的方法,使得地图类型和节点可以摆脱依赖,便于后面实现同种类的地图不同的节点。

地图生成部分定义了一个生成配置类和生成类,配置类负责配置要生成的地图种类,地图所处的平面,以及各种类地图的一些独有参数。生成类依赖配置来创建具体的地图,并为其绑定对应的显示。

系统完整类图

MapGridInUnity类图.drawio
看不清可以去这里查看。

额外的实现细节

系统的整体结构与设计如上文所示,为了实现地图的通用和寻路通用,还有一些比较巧妙的设计,这里进行补充阐述。

  • 在寻路的时候,经常会需要从一个节点访问到该节点的一圈邻居,但是不同的地图,获取某个节点邻居的方式不同,为了通用我们需要定义一个方法,能直接获取到某节点的所有邻居。本系统定义了一个IDir接口,用来获取一个节点四周邻居相对于该节点的索引偏移,这样在寻路时可以通过该节点和索引偏移计算出周围所有邻居的节点。在网格地图中,分为了两种,一种是四方向的,一种是八方向的,对应的索引偏移列表不同。而对于六边形地图,则是另一种索引偏移,所以在本系统中,分别实现了三个具体实现,并通过配置来决定使用哪组偏移列表。
  • 为了高效在六边形地图中实现范围高亮,六边形使用了Cube coordinates,这个名词来自于Amit Patel的《Hexagonal Grids 》中,其使用了三个轴来表示每个节点,使得在访问邻居时,可以在三个轴上做索引偏移,大大减少了查找邻居的消耗。这里我最开始是使用了偏移坐标,但是在实际去高亮大范围节点时发现并没有那么轻松,尤其是高亮可能发生在地图边缘,后面忍痛对此做了重构改用立方体坐标了。
  • 在处理扇形高亮时,实际上就是从圆形高亮中抠出一部分,因此其内部是判断一个朝向,并根据扇形宽度算出扇形左右最大偏移角,最后调用圆形高亮的方法并添加一个角度的Filter对节点做筛选。
  • 地图配置类中,增加了编辑器类,来对配置类Inspector界面做个性化显示,根据选取的地图类型,来展示该类型所需要的独有参数,并隐藏无关的参数。

总结

以上便是整个地图系统的全部内容和设计思路了,在类图中,箭头代表了依赖关系走向,A指向B表示A依赖B。从图中不难看出,箭头指向的对象基本都是接口,抽象类,或者是一些不太会发生变化的东西。如数据结构小节中的图示,即便依赖的对象是具体实现,我们也可以引入更抽象的接口对象,实现依赖反转,使得整个依赖关系走向更合理,系统更稳定可靠。当然这个系统并不完善,也可能不如料想的那般好用,但我希望通过开源出来给更多的人看见,给更多的人使用,并提供反馈来完善这个东西,使得其可以代代相传(doge。

项目地址:

https://github.com/tang-xiaolong/MapGridInUnity

引用:

  1. Amit Patel.《Hexagonal Grids 》https://www.redblobgames.com/grids/hexagons/
  2. Catlike Coding.《Hex Map》https://catlikecoding.com/unity/tutorials/hex-map/
  3. Robert C.Martin. 《架构整洁之道》

相关内容

热门资讯

安卓系统能跑win吗,探索跨平... 你有没有想过,你的安卓手机里能不能装上Windows系统呢?这听起来是不是有点像科幻电影里的情节?别...
安卓车载系统蓝牙设置,畅享智能... 你有没有发现,现在开车的时候,手机和车载系统之间的互动越来越频繁了呢?这不,今天就来给你详细说说安卓...
奥利奥安卓系统,探索新一代智能... 你有没有想过,一块小小的奥利奥饼干竟然能和强大的安卓系统扯上关系?没错,今天就要来聊聊这个跨界组合,...
微信使用安卓系统,功能解析与操... 你有没有发现,现在用微信的人越来越多了呢?尤其是安卓系统的用户,简直就像潮水一样涌来。今天,就让我带...
体验最新原生安卓系统,极致体验... 你有没有想过,手机系统就像是我们生活的调味品,有时候换一种口味,生活都会变得有趣起来呢?最近,我体验...
安卓系统能玩原神,尽享奇幻冒险... 你有没有想过,在安卓系统上也能畅玩《原神》这样的热门游戏呢?没错,就是那个画面精美、角色丰富、玩法多...
安卓写手机银行系统,基于安卓平... 你有没有想过,手机银行系统在我们日常生活中扮演了多么重要的角色呢?每天刷刷手机,就能轻松管理账户,转...
僵尸之夜恐怖安卓系统,揭秘恐怖... 僵尸之夜,恐怖安卓系统来袭!想象一个寂静的夜晚,你正沉浸在美梦中,突然,一阵诡异的铃声打破了夜的宁静...
谷歌框架和安卓系统,构建智能移... 你有没有想过,为什么你的手机那么聪明,能帮你找到路线,还能帮你拍出美美的照片呢?这都要归功于一个超级...
安卓系统和oppo系统哪个流畅... 你有没有想过,手机系统哪个更流畅呢?安卓系统和OPPO系统,这两个名字听起来就让人心动。今天,咱们就...
安卓怎么用微软系统,利用微软系... 你是不是也和我一样,对安卓手机上的微软系统充满了好奇?想象那熟悉的Windows界面在你的安卓手机上...
安卓系统如何安装nfc,安卓系... 你有没有想过,用手机刷公交卡、支付账单,是不是比掏出钱包来得酷炫多了?这就得归功于NFC技术啦!今天...
ios系统可以转安卓,跨平台应... 你有没有想过,你的iPhone手机里的那些宝贝应用,能不能搬到安卓手机上继续使用呢?没错,今天就要来...
iOSapp移植到安卓系统,i... 你有没有想过,那些在iOS上让你爱不释手的app,是不是也能在安卓系统上大放异彩呢?今天,就让我带你...
现在安卓随便换系统,探索个性化... 你知道吗?现在安卓手机换系统简直就像换衣服一样简单!没错,就是那种随时随地、随心所欲的感觉。今天,就...
安卓系统安装按钮灰色,探究原因... 最近发现了一个让人头疼的小问题,那就是安卓手机的安装按钮突然变成了灰色,这可真是让人摸不着头脑。你知...
安卓7.1.1操作系统,系统特... 你知道吗?最近我在手机上发现了一个超级酷的新玩意儿——安卓7.1.1操作系统!这可不是什么小打小闹的...
安卓os系统怎么设置,并使用`... 你有没有发现,你的安卓手机有时候就像一个不听话的小孩子,有时候设置起来真是让人头疼呢?别急,今天就来...
安卓降低系统版本5.1,探索安... 你知道吗?最近安卓系统又来了一次大动作,竟然把系统版本给降到了5.1!这可真是让人有点摸不着头脑,不...
解放安卓系统被保护,解放安卓系... 你有没有想过,你的安卓手机其实可以更加自由地呼吸呢?是的,你没听错,我说的就是解放安卓系统被保护的束...