以是NPC在一些游戏中是有着至关主要的位置的,那么本日就来探索一下在新版Unity中自动寻路是怎么操作的?
代码示例仓库地址:https://gitee.com/jeady5/unity3dSample
演示视频放在《微代码人生》,项目是一些理论性的知识。
二、目标本次分享的终极目标是从零开始实现NPC的巡逻、跟随、呼叫。
以上三个问题的核心便是Unity的寻路系统,将寻路系统搞明白之后,三个问题,也就迎刃而解了。
三、组件先容关于寻路系统的几个干系组件的简介如下:
NavMeshSurfaceThe 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烘焙
NavMeshAgentNavMeshAgent components help you to create characters which avoid each other while moving towards their goal. Agents reason about the game world using the NavMeshand 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的设置。如下区域类型图:
你可以设置不同类型路段的花费情形,你也可以设置水路比平路花费体力少,统统随你心意。
NavMeshModifierVolumeNavMesh 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寻路的查找范围。
NavMeshLinkNavMesh Link creates a navigable link between two locations that use NavMeshes.
【NavMeshLink组件】
该组件许可你连接两个普通寻路不能抵达的点。如飞檐走壁,翻过栏杆等。
OffMeshLinkOffMeshLink component allows you to incorporate navigation shortcuts which cannot be represented using a walkable surface.
【OffMeshLink组件】
该组件和NavMeshLink的功能相同,唯一不同之处在于他们指定两点的办法。
NavMeshLink 须要你输入两个位置坐标即可。OffMeshLink 连接的是两个游戏工具。
各有利害,根据实际进行选用即可。
NavMeshObstacleThe 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单独巡逻,直到碰着主角,便决定跟随他一起去取经。
如果对你有些许帮助,欢迎三连见告朋友。