Unity3D之Navigation导航系统学习及案例讲解(适合初学者)

引言:很多游戏都有自动寻路功能,点击场景中的一个位置,角色会自动选择一条相对较优的路线过去。大多数端游页游都会使用A*寻路算法,小生之前也总结过,刚兴趣的可以学习一下。现在学习的是Unity内置的导航系统,并结合案例进行讲解。
开发版本:Unity 2017.1.1f1、VS 2017

适合人群:初学Unity者

一.导航系统定义

在Unity手册中是这样定义的:The Navigation System allows you to create characters which can navigate the game world. It gives your characters the ability to understand that they need to take stairs to reach second floor, or to jump to get over a ditch. 

大致翻译为:导航系统允许你创建一个在游戏世界中能导航的角色。它可以让你的角色有能力去理解他们需要去爬楼梯到二楼,或者跳越一条沟渠。(本人英语翻译能力有限哈!)

二.基础知识

1.导航网格Nav Mesh

首先需要将地形设置为Navigation Static,如下图所示:

如果有不想烘焙的地方,取消勾选即可。打开Window-Navigation导航窗口,选择Bake页面,如下所示:


  • Agent Radius:定义网格和地形边缘的距离
  • Agent Height:定义可以通行的最高度
  • Max Slope:定义可以爬上楼梯的最大坡度
  • Step Height:定义可以登上台阶的最大高度
  • Drop Height:允许最大下落距离
  • Jump Distance:允许最大的跳跃距离

设置好后,可以点击Bake进行烘焙,导航网格效果如下图所示:


2.Nav Mesh Agent

为角色添加NavMeshAgent组件,用来控制角色在导航网格上移动,Unity版本不同,可能面板不太一样,如上所示:

  • Steering(操纵)
  • Speed:最大移动速度
  • Angular Speed: 行进时的最大角速度
  • Acceleration:最大加速度,控制速度的变化快慢
  • Stopping Distance:制动距离,到达目标点的距离小于这个值
  • Auto Braking:勾选,到达目标点后停止运动,没有缓冲运动

常用API:

  • ActivateCurrentOffMeshLink :激活或禁止当前off-MeshLink. 
  • CalculatePath :计算到某个点的路径并储存 
  • CompleteOffMeshLink :完成当前offMeshLink的移动 
  • Move :移动到相对于当前位置的点 
  • ResetPath :清除当前路径 
  • SetDestination :设置目标点 
  • SetPath :设置一条路线 
  • Warp :瞬移到某点
  • remainingDistance:到目标点的距离
  • desiredVelocity:期望速度,方向指向的是到达目标点的最短路径的方向

3.Nav Mesh Area

用来设置路径估值(Cost),比如走楼梯,消耗体能20,而坐电梯,消耗体能5,自然会选择后者方式。

设置完消耗代价后,在Object面板中设置类型

Unity内置了三种area,Walkable设置可行走区域,NotWalkable设置不可行走区域,如果不想让角色行走的区域,可以设置成这个。需要注意,做了修改,一定要重新烘焙网格,设置才会有效哦!

4.Off Mesh Links

地形之间可能有间隙,形成沟壑,或者是高台不能跳下,导航网格处于非连接的状态,角色无法直接跳跃,要绕一大圈才能到达目的地。off mesh links用于解决这种问题。

可以自动或者手动创建off mesh links,需要先设置bake选项卡中的Drop Height或者Jump Distance属性,前者控制跳跃高台最大高度,后者控制跳跃沟壑的最大距离。

选中需要创建Links的对象,在Object 选项卡内勾选Generate OffMeshLinks,再重新烘焙即可。需要注意,这里平台1设置了Links,而平台2没有设置。此时,角色只能从平台1跳到平台2,如下图箭头所示:

手动添加Links,需要为地形对象添加off mesh link组件,可以创建两个空对象,分别用来控制跳跃的开始和结束点,如下所示:


  • Cost Override:路径估值,和之前的Area一样
  • Bi Directional:控制跳跃是单向的还是双向的
  • Activated:控制Link是否激活
  • Auto Update Position:自动更新位置,当移动开始结束点的时候,自动更新

5.Nav Mesh Obstacle

  • Shape:选择障碍的几何形状
  • Carve:如果勾选,会重新渲染网格,效果如下所示

三.案例讲解

实现点击目标,自动寻路功能,效果如下:


前期准备:渲染好导航网格,在玩家身上挂载Nav Mesh Agent组件

添加如下脚本:

public class Player : MonoBehaviour
{
    private NavMeshAgent navMeshAgent;

    private void Start()
    {
        navMeshAgent = gameObject.GetComponent<NavMeshAgent>();
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray,out hit))
            {
                Transform parent = hit.collider.transform.parent;
                if (parent != null && parent.name.Equals("Env"))
                {
                    navMeshAgent.SetDestination(hit.point);
                }
            }
        }
    }
}

下面实现代码控制角色移动,navMeshAgent.updatePosition = false; navMeshAgent.updateRotation = false;可以禁止Agent更新位置和旋转。但会造成Agent的绿框和角色分离,如下图所示,设置绿框的位置和角色位置相同即可解决问题,navMeshAgent.nextPosition = transform.position;


public class Player : MonoBehaviour
{
    private NavMeshAgent navMeshAgent;

    private void Start()
    {
        navMeshAgent = gameObject.GetComponent<NavMeshAgent>();
        //禁用NavMeshAgent更新角色位置
        navMeshAgent.updatePosition = false;
        navMeshAgent.updateRotation = false;
    }

    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(ray,out hit))
            {
                if (hit.collider.name.Equals("Floor"))
                {
                    navMeshAgent.nextPosition = transform.position;
                    navMeshAgent.SetDestination(hit.point);
                }
            }
        }
        Move();
    }

    private void Move()
    {
        if (navMeshAgent.remainingDistance < 0.5f) return;
        navMeshAgent.nextPosition = transform.position;
        if (navMeshAgent.desiredVelocity == Vector3.zero) return;
        Quaternion targetQuaternion = Quaternion.LookRotation(navMeshAgent.desiredVelocity,Vector3.up);
        transform.rotation = Quaternion.Lerp(transform.rotation, targetQuaternion, Time.deltaTime *3);
        transform.Translate(Vector3.forward * Time.deltaTime*3);
    }
}

其他可以参考学习的博客:

https://www.jianshu.com/p/70da4f9461ae

https://blog.csdn.net/janeky/article/details/17457533

https://www.jianshu.com/p/f9a32d293d2f


  • 32
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Unity作为一款广泛使用的游戏开发引擎,在游戏开发领域中有着举足轻重的地位。如果想要开始学习Unity引擎,需要掌握基础概念和技能。以下是Unity零基础到入门的步骤: 第一步是了解Unity的界面和基本概念,包括场景、游戏对象、组件等,这些是搭建Unity工程的基础。 第二步是学习Unity中的脚本编程,以及常用的变量类型、条件语句、循环语句等基本语法知识。 第三步是掌握Unity的资产管理和使用,包括材质、纹理、声音、动画等。 第四步是了解Unity中的游戏物理系统,包括刚体、碰撞器等,以及如何添加和控制它们。 第五步是学习Unity中比较重要的导航系统,这就需要我们详细解析这个系统的操作步骤和注意事项,这个过程就需要用到"万字教程"。 Unity导航系统是一个专门用于实现寻路和移动的功能,它可以在场景中自动生成地图,并自动计算出路线、寻找路径和避免障碍物。导航系统的基本原理是通过使用寻路算法来查找最短路径,这个算法需要用到A*算法,这也是一个常用的寻路算法。在具体操作中,用户需要首先添加导航网格、设置导航代理、通过设置导航区域建立环境信息来让导航代理获取路径信息等步骤,最终通过代码实现控制游戏对象移动的过程。 总之,要学习Unity导航系统,需要先获得一定的Unity基础,学习并熟练掌握资产管理、物理系统、脚本编程等技能,并结合"万字教程"对导航系统进行深入学习和了解,最终掌握实现游戏导航的技巧和操作。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值