导航网格指的是游戏场景中可以通过的区域。在 Unity 中,我们只需要指定场景中哪些游戏对象参与导航网格的计算,就可以自动生成导航网格。
生成导航网格的步骤:
1.选中所有参与计算的游戏对象,在 Inspector 视图中展开 Static 下列列表选中 Navigation Static 选项。
2.执行菜单:Window -> AI -> Navigation ,打开 Navigation 面板。在该面板中的有 4 个选项卡分别是:Agents、Areas、Bake、Object,选中 Bake 选项卡,单击 Bake 按钮。
3.Bake 完成后在场景中会出现 Bake 网格,网格内的区域就是允许导航的区域。如下图所示:
Bake 属性如下:
导航代理是一个独立的组件,给游戏角色添加 Nav Mesh Agent(导航网格代理)组件后,角色就会在导航区域中进行导航移动。
Nav Mesh Agent 组件属性:
使用脚本控制导航:
当场景中导航网格已经生成,游戏角色也挂载了导航代理组件后,接下来就可以为游戏角色添加脚本,在脚本中控制导航进行移动。
示例:单击场景中的位置作为目标点,使角色朝目标点移动,并最终到达目标点。代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class PlayerController : MonoBehaviour
{
private NavMeshAgent _agent;
// Start is called before the first frame update
void Start()
{
_agent = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
bool res = Physics.Raycast(ray, out hit);
if (res)
{
Vector3 point = hit.point;
_agent.SetDestination(point);
}
}
}
}
12.3 障碍物
在导航网格生成时,静态障碍物会自动生成好,但在游戏中经常会遇到动态障碍物,对于动态障碍物,需要使用 Nav Mesh Obstacle(导航网格障碍)组件。
Nav Mesh Obstacle 组件属性:
在添加障碍物时,除了要挂载 Nav Mesh Obstacle 组件外,还要为障碍物物体取消勾选 Static 选项。
示例:通过障碍物控制胶囊体移动。
1.新建项目,在场景中添加一个 Plane,缩放为 (2,2,2),添加一个胶囊体,命名为 NPC,并给 NPC 添加 Nav Mesh Agent 组件。
2.在 Project 视图中创建脚本 NPCController,并挂载到 NPC 物体上,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class NPCController : MonoBehaviour
{
// 导航代理组件
private NavMeshAgent _agent;
// 目标点
private Vector3 targetPosition;
// 是否到达目标点
private bool isArrived = false;
// Start is called before the first frame update
void Start()
{
_agent = GetComponent<NavMeshAgent>();
targetPosition = transform.position new Vector3(0, 0, 10);
_agent.SetDestination(targetPosition);
}
// Update is called once per frame
void Update()
{
// 获取距离目标点的距离
float dis = Vector3.Distance(transform.position, targetPosition);
if (_agent.remainingDistance < 0.1f)
{
// 在与目标点的距离小于 0.1 的情况下
if (isArrived)
{
// 在开始位置
isArrived = false;
// 向终点移动
targetPosition = transform.position new Vector3(0, 0, 10);
}
else
{
// 在终点位置
isArrived = true;
// 向开始点移动
targetPosition = transform.position - new Vector3(0, 0, 10);
}
_agent.SetDestination(targetPosition);
}
}
}
3.选中 Plane,执行 Window -> AI -> Navigation ,在 Inspector 视图中勾选 Navigation Static,单击 Bake 选项卡,单击 Bake 按钮。
4.在场景中添加立方体,命名为 Player,位置为(-0.15,1,-3),缩放为(8,2,0.4),给 Player 添加 Nav Mesh Obstacle 组件。
5.在 Project 视图中创建脚本 PlayerController,并挂载到 Player 上,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
float h = Input.GetAxis("Horizontal");
transform.position = transform.right * h * 0.3f;
}
}
运行游戏,我们会发现,无论怎么样移动障碍物,NPC 都会自动躲避障碍物。
12.4 导航网格链接网格之间可以设置网格链接。在导航网格生成时,Bake 选项卡中的 Generated Off Mesh Links 中包括 Drop Height(掉落高度)和 Jump Distance(跳跃距离),这个两个属性运行从高台掉落并在高台间跳跃。同时,选中场景中的高台物体(一个或多个),在 Object 选项卡中勾选 Generate Off Mesh Links 选项,然后再在 Bake 选项卡中单击 Bake 按钮,Bake 完成后,可以看到高台的附加自动生成链接,这样角色就可以在链接之间移动了。
上面我们说明的是通过 Bake 自动生成导航网格链接,在实际开发中,我们会需要自己控制网格间的链接,也就是说,我们希望能从某点到另外一点生成一个链接。这时,就需要用到 Off Mesh Link 组件。
Off Mesh Link 组件属性:
Start - 网格链接起始位置的游戏物体。
End - 网格连接结束位置的游戏物体。
Cost Override - 网格链接花费的成本。
Bi Directional - 是否允许双向移动。
Actived - 是否已激活该网格链接。
Auto Update Positions - 是否自动更新位置,勾选后,当起始或结束位置的对象移动时,会更新网格链接。
Navigation Area - 导航区域,网格链接属于的导航区域。
创建网格链接的步骤:
创建一个平面,缩放为(0.03,0.03,0.03),复制一份,并将两个平面放在希望进行网格链接的两个位置。
选择其中一个添加 Off Mesh Link 组件,然后将两个平面分别放在组件的 Start 和 End 处。即可看到生成的网格链接,如下图所示:
12.5 导航区域在 Navigation 面板上,Areas 选项卡中,一共可以设置 32 个区域,默认设置了 3 个区域,其余区域可以自定义,每个区域都会有颜色和成本的设置。
成本的含义为导航代理网格移动时消耗的体力,导航系统在计算推荐路线时会将成本计算在内。
示例:让胶囊体在规划的路线上移动。
1.新建项目,并在场景中添加 1 个 平面和 8 个 立方体(路面)、1 个胶囊体(角色),形成如下图所示场景:
2.打开 Navigation 面板(Window -> AI -> Navigation),单击 Areas 选项卡,增加一个 Road 区域,设置成本为 1,Walkable 成本为 100。
3.单击一个立方体,在 Navigation 面板中的 Object 选项卡这设置 Navigation Area 为 Road(其他立方体也是如此)。
4.选择 1 个 平面和 8 个 立方体,在 Navigation 面板中 Bake 选项卡中单击 Bake 按钮,完成后如下图所示:
5.在 Project 视图中创建脚本 PlayerController,挂载到胶囊体,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class PlayerController : MonoBehaviour
{
private NavMeshAgent _agent;
// Start is called before the first frame update
void Start()
{
_agent = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
bool res = Physics.Raycast(ray, out hit);
if (res && hit.collider.gameObject.name != "Plane") // 只能在非 Plane 上移动
{
Vector3 point = hit.point;
_agent.SetDestination(point);
}
}
}
}
运行游戏,看看效果,应该是只有在单击立方体时才会移动,移动时是沿着立方体的表面移动的,而不会走 Plane 绿色的区域。
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved