Unity中实现合理塔防寻路机制

2024-01-26 13:28

本文主要是介绍Unity中实现合理塔防寻路机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在一款TD游戏中,最重要的单位就两大类:防御塔(Tower)和敌人单位(Enemy)。在处理敌人单位的AI行为时,最基本也是最重要的就是自动寻路。在各式TD游戏中,防御塔的攻击方式以及敌人单位的Buff机制往往是能做出差异化的地方;而在寻路问题上,几乎是没有差异的,面对的都是同一套问题模型。

以魔兽争霸中的TD地图、KingdomRush为代表的这一类”固定路径,固定塔位“的寻路模型是最为常见的。本文对于寻路问题所参照实现的,则是久负盛名的Defense Grid(中文译名防御阵型);作为最经典的TD游戏之一,不仅是因为其在早年发布的第一部作品中就表现出了非常优秀3D画面,更重要的是在前述的寻路模式下引入了新的机制:允许在敌人单位的前进路线上放置防御塔或障碍物,从而在运行时动态地改变路径。这一创新极大的提高了可玩性,在此之后许多流行的TD游戏都有使用这种寻路方式 例如Infinitode、X-Morph、国产游戏重构Refactor等。

寻路问题的建模

我们首先要做的是根据游戏中的地图特征,将所有能够行走的地面抽象为数据结构,然后再决定合适的寻路算法。

对于路径建模有三种主流方式,我们以下图作为原版地图来说明:

image

格子(Grid)

image

格子模型将地图分割为许多大小相等的格子,利用二维数组存储起来。使用各种值表示数组中对应的位置类型 如0用来表示障碍物,1表示可行走的区域。

优点:

  • 实现简单
  • 易于在运行时动态修改

缺点:

  • 如果想更为细致地表达路径,则需要将格子分割地更小,从而导致内存占用更大且大范围寻路时计算代价更大

对于2D画面的小地图,是该模型最适合的场景。笔者在刚上大学时写过一个2D的塔防游戏,当时就是以这种方式来处理地图的(https://www.cnblogs.com/geek1116/p/5953456.html)

路径点(WayPoint)

image

这种方式需要在手动标注出所有可以行走的点,这些点互相连接的直线就是单位行走的路径。通常在这些连接边上还需要带上权重,用邻接表的数据结构存储。

优点:

  • 内存占用小
  • 在此基础上做寻路算法的计算代价小

缺点:

  • 需要人工添加路径点,且在地图变动后都需要再次调整路径点,工作量大
  • 由于单位只能沿着路径点行走,行为方式在观感上会表现的较为生硬,不够灵活;在大地图范围寻路以及需要考虑单位碰撞的场景下,该问题更为明显

对于传统的固定线路的塔防中,WayPoint是非常适合的建模方式

导航网格(NavMesh)

image

通过一系列的算法将可行走地形转换为由若干凸多边形组成的网格,并维护多边形之间的邻接关系。在导航网格中求两点之间的移动路径,需要根据两点所在的多边形以及多边形之间的邻接关系,按照某种寻路算法找出需要经过的所有多边形;再根据拐点算法计算途中的各个拐点来得出”平滑“的移动路径。

优点:

  • 相比于前两种模型,NavMesh更能表达出地形的特征
  • 适用于3D地形

缺点:

  • 建模过程复杂,自己从零造轮子的话实现成本很大
  • 不便于动态修改;在修改地形后再重新烘焙NavMesh的过程比较耗时,想要运行时执行这一过程的话性能代价较大

Unreal Engine、Unity等游戏引擎中的导航系统内部原理都是基于NavMesh的

寻路算法

三种经典的路径规划算法:

  • 广度优先搜索(BFS)
  • Dijkstra最短路算法
  • A*算法(A star)

在游戏开发中实现寻路问题时,A*算法通常是不二之选。这也是Unity中采用的寻路算法。

如果是以WayPoint的方式作地图建模的话,那么数据结构存储的是一个无向加权图,在此之上进行路径规划,Dijkstra算法通常会是一个合适的选择。

在塔防游戏中选择合适的寻路方案

回到我们的主题,要以Defense Grid为蓝本在Unity中实现敌人单位的寻路。

最简单粗暴是使用游戏引擎自带的导航系统,给定一个终点后剩下的都交给导航系统去处理了。这种方式下单位在地图上寻路时所走的都是近似最短路的路线。这种方式不能说是错的,但从游戏设计的角度讲 这种表现方式显得”很蠢“:在游戏实际运行中,敌人单位是一波一波出现的,但同一波次中的若干敌人在前进时会显得完全没有”集体意识“,大家都各自为战,最终会挤到同一条直线上。如下所示:

image

以右上方红点设为目的地,三个单位都只从自身位置考虑,算出当前到终点的最短路线;当经过第一个拐点后,它们仨都会位于同一直线上前行。

笔者曾关注过的塔防作品中确实见到过极个别真是这么实现的......

我们在前文提到过,对于固定路线的这类型地图寻路中可以采用WayPoint的方式建模,单位的前进路线则按着路径点之间的走,但这仍然会存在上述的问题。在Unity中做个demo,尝试下在两个拐

这篇关于Unity中实现合理塔防寻路机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/646945

相关文章

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

opencv图像处理之指纹验证的实现

《opencv图像处理之指纹验证的实现》本文主要介绍了opencv图像处理之指纹验证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、简介二、具体案例实现1. 图像显示函数2. 指纹验证函数3. 主函数4、运行结果三、总结一、