龙空技术网

Unity 之新版AI自动寻路系统

jeady5 56

前言:

今天朋友们对“unity 寻路路径”大概比较重视,咱们都需要分析一些“unity 寻路路径”的相关资讯。那么小编同时在网络上汇集了一些关于“unity 寻路路径””的相关文章,希望朋友们能喜欢,朋友们一起来学习一下吧!

Unity 之角色/NPC的新版自动寻路系统一、概述

喜欢游戏的朋友都知道,游戏中会有NPC(non-Player-Character, 非玩家角色)的出现,他可能是发任务领奖赏的人, 也可能是按规定路线行走巡视的小兵/野怪,或是你身边的宠物/侍从…

所以NPC在一些游戏中是有着至关重要的位置的,那么今天就来探索一下在新版Unity中自动寻路是怎么操作的?

代码示例仓库地址:

演示视频放在《微代码人生》,项目是一些理论性的知识。

二、目标

本次分享的最终目标是从零开始实现NPC的巡逻、跟随、呼叫。

巡逻:

当主角没有靠近NPC时,在指定范围内进行巡逻。跟随:

当主角抵达NPC周围时,实现自动认主并跟随主角。呼叫:

当主角与NPC单独行动时,主角可以念紧箍咒让NPC自动寻路找到主角。

以上三个问题的核心就是Unity的寻路系统,将寻路系统搞明白之后,三个问题,也就迎刃而解了。

三、组件介绍

关于寻路系统的几个相关组件的简介如下:

* NavMeshSurface

The NavMesh Surface component represents the walkable area for a specific NavMesh Agent type, and defines a part of the Scene where a NavMesh should be built.

【NavMeshSurface组件】

通过添加该组件,使用其烘焙(bake)功能, 即可将场景中的诸多物体按照已设定的参数构建出代理角色可行走的区域。

可以简单理解为该组件就是一个地形的探测者,他可以绘制出无形的场景地图。告知旅行者哪里能到达,哪里无法到达。

注: 当场景中物体位置发生改变后,记得重新Bake烘焙

* NavMeshAgent

NavMeshAgent components help you to create characters which avoid each other while moving towards their goal. Agents reason about the game world using the NavMesh

and they know how to avoid each other as well as other moving obstacles. Pathfinding and spatial reasoning are handled using the scripting API of the NavMesh Agent.

NavMeshAgent组件

【NavMeshAgent组件】

将该组件添加到需要实现自动寻路导航的任何物体上,便可通过一个简单的目的地坐标自动寻路过去。

简单理解为按照NavMeshSurface生成的地图进行导航的旅行者。该旅行者还可分为高矮胖瘦,跳的高的,走得快的… 另外,你还可以指定该旅行者可以去的区域,比如不能走水路;只能走水路等等。

使用示例(假设脚本中已经获取到了代理信息agent: NavMeshAgent):

// 只需要一句设置其目的地属性的代码,就可以让他自动躲避已有障碍物,沿着地图行走过去。agent.destination = new Vector3(10, 0, 10);
NavMeshModifier

NavMesh Modifiers adjust how a specific GameObject behaves during NavMesh baking at runtime.

【NavMeshModifier组件】

该组件允许你去修改当前物体属于什么类型的路面(如马路,水路,不可走区域)。该路面信息可通过AreaType进行添加。为NavMeshSurface烘焙地图提供参考。

该组件在本文视频中未涉及,想象一个实例,当我们想去一个地方的时候,肯定会有多种选择,比如走着去,开车去等等,我们就会在这几种方式进行权衡,比如我想快点到,我就会去权衡时间问题,哪个快,我就选择哪一个。

同样,在AI导航有多种路径可供选择时,他就会根据各路径的花费去选择花费最少的那一条。

举个例子:NPC要过河,他可以游泳过去,也可以走桥过去,他会选择最优的那条路,取决于在Unity中你对AreaType的设置。

如下区域类型图:

你可以设置不同类型路段的花费情况,你也可以设置水路比平路花费体力少,一切随你心意。

NavMeshModifierVolume

NavMesh Modifier Volume marks a defined area as a certain type (for example, Lava or Door). Whereas NavMesh Modifier marks certain GameObjects with an area type. NavMesh Modifier Volume allows you to change an area type locally based on a specific volume.

【NavMeshModifierVolume组件】

和NavMeshModifier类似,也是划定地形的类型,不同的是该组件允许你自定义任何区域,而不只是限制到已存在的物体之上。

通过该组件你可以任意指定某个区域是安全,某个区域是危险区域等。以限制AI寻路的查找范围。

NavMeshLink

NavMesh Link creates a navigable link between two locations that use NavMeshes.

【NavMeshLink组件】

该组件允许你连接两个普通寻路不能抵达的点。如飞檐走壁,翻过栏杆等。

OffMeshLink

OffMeshLink component allows you to incorporate navigation shortcuts which cannot be represented using a walkable surface.

【OffMeshLink组件】

该组件和NavMeshLink的功能相同,唯一不同之处在于他们指定两点的方式。

NavMeshLink 需要你输入两个位置坐标即可。

OffMeshLink 连接的是两个游戏对象。

各有优劣,根据实际进行选用即可。

NavMeshObstacle

The Nav Mesh Obstacle component allows you to describe moving obstacles that Nav Mesh Agents should avoid while navigating the world (for example, barrels or crates controlled by the physics system). While the obstacle is moving, the Nav Mesh Agents do their best to avoid it. When the obstacle is stationary, it carves a hole in the NavMesh. Nav Mesh Agents then change their paths to steer around it, or find a different route if the obstacle causes the pathway to be completely blocked.

【NavMeshObstacle组件】

静态障碍物在NavMeshSurface进行Bake烘焙时就已经固定了,通过添加该组件,你可以实现动态障碍物的效果,简单说就是当障碍物移动时,AI寻路时也能绕开。

最后,在地形改动之后一定记得要重新烘焙。

四、其他相关点击屏幕转为位置信息。单物体的简单检测

从场景的主相机位置向屏幕点击点发出一条指定长度的射线,Physics.Raycast 方法将返回第一个被击中的游戏对象以及相应的信息(如击中点的位置信息),使用示例如下:

if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 100)) {   Debug.Log("hit a point: " + hit.point);    agent.destination = hit.point;}
多物体下的过滤检测

如果中间还有其他游戏物体,可能击中点并不是地面的可行走区域,此时可以使用Physics.RaycastAll,来获取被射线击中的全部物体的信息,并从中过滤。如:

RaycastHit[] hits = Physics.RaycastAll(Camera.main.ScreenPointToRay(Input.mousePosition), 100);foreach (RaycastHit hit in hits){    if(hit.transform.name.Equals("ground")){       Debug.Log("hit a point: " + hit.point);        agent.destination = hit.point;       break;    }}
检测周围存在的物体

与上述方法类似,可以使用Physics.OverlapSphere方法,可以获取处于给定位置和半径球体内的物体的列表。比如检测指定范围内是否有一个叫Player的角色物体:

Collider[] hitColliders = Physics.OverlapSphere(transform.position, 2);foreach (var hitCollider in hitColliders){    if(hitCollider.name.Equals("Player"){        // ...    }}
武、最后

看得懂再多也无法吸收,不如去手动实践一下,总会发现不足之处。

下述视频实现了NPC单独巡逻,直到遇到主角,便决定跟随他一起去取经。

如果对你有些许帮助,欢迎三连告诉朋友。

标签: #unity 寻路路径 #3d游戏易语言自动寻路 #unity巡逻算法自动寻路 #unity敌人自动巡逻攻击 #unity自动寻路并攻击