2017-03-09 11:16:50 qq_23225317 阅读数 658
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4643 人正在学习 去看看 张刚

Nav Mesh导航网格是3D游戏中实现动态物体自动寻路的技术

2018-11-21 09:08:22 weixin_42046850 阅读数 199
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4643 人正在学习 去看看 张刚

旋转(欧拉、矩阵)

1.Transform:position(平移)、rotation(旋转)、scale(缩放)。

2.四元数:应于transform组件中的rotation属性,这个属性的类型其实就是四元数。

3.控制旋转的两种方式:矩阵旋转,欧拉旋转。

4.矩阵旋转:使用一个4*4的矩阵来表示绕任意轴旋转时的变换矩阵,特点:乘以一个向量的时候只改变向量的方向而不会改变向量的大小;

5.欧拉旋转:在旋转时,按照一定的顺序(例如:x、y、z,Unity中的顺序是z、x、y)每个轴旋转一定的角度,来变换坐标或者是向量,实际上欧拉旋转也可以理解为:一系列坐标旋转的组合;

6.组件旋转的方法:  

 ①:transform.Rotate(Vector3 eularAngles Space relativeTo) //transform组件方法


 ②:xxx.transform.localrotation=Quaternion.Euler(0.0f,0.0f,0.0f);该属性表示了在父节点坐标系中的旋转情况。通常使用四元数来进行初始化。


 ③:xxx.transform.localEulerAngles = new Vector3 (0.0f,0.0f,0.0f);该属性也表示了在父节点坐标系中的旋转情况,只是直接通过欧拉角来初始化

④:xxx.transform.rotation=Quaternion.Euler(0.0f,0.0f,0.0f);该属性表示了在全局坐标系下的旋转情况。通常使用四元数来赋值。

导航网格

1.Windown->Ai->Navgation(所有环境相关的勾选Static)


2.    Nav面板->Object->勾选NavStatic->Bake


3、Max Slope 斜坡斜度(最大60°),如果大于设定值就不会生成网格。 


4、Step Height 台阶高度 ps这个高度不可以大于人的高度。 
5、Drop Height 允许的最大下落距离。 
6、Jump Distance 允许的最大跳跃距离。 
7、Agent Height:物体导航范围(推荐0.2)
8、取消物体阻挡:选中物体:Inspector面板:取消勾选NavStatic
8、取消物体上方导航网格:选中物体。Nav面板中Object的NavArea选项NotWallkable

2016-05-10 17:25:36 prcfiona 阅读数 4232
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4643 人正在学习 去看看 张刚

Unity中对于寻路导航算法进行了封装,支持提交将地图进行导航烘焙

如果想在两个不连续的平面之间加一个吊桥,在桥放平时可以使物体通过吊桥,而桥抬起时物体在桥边等待。
地形示意图
1. 给桥的加一个旋转中心如图中蓝色球体,将桥和地面分开,设置两个地面的Navigation值如图,勾选Navigation Static和Generate OffMeshLinks,Navigation Area的值设为Walkable
地面的Navigation值
2. 设置桥体的Navigation值如图,同样勾选Navigation Static和Generate OffMeshLinks,如图在Areas添加标签bridge,并将Navigation Area的值设为bridge
这里写图片描述
3. 给物体1添加组件Navigation->Nav Mesh Agent
这里写图片描述
4.给桥添加脚本代码如下

 private Transform Sphere;
    private bool isOver;
    private GameObject src;
    // Use this for initialization
    void Start ()
    {
        isOver = false;
        Sphere = GameObject.Find("Sphere").transform;
        transform.RotateAround(Sphere.position, Vector3.left, 45);
        src = GameObject.Find("src");
    }

    // Update is called once per frame
    void Update ()
    {
        if(!isOver&&Time.realtimeSinceStartup > 5)
        {
            transform.RotateAround(Sphere.position, Vector3.left, -45);
            isOver = true;
            src.SendMessage("SendMask", -1);
        }

    }

5.给物体1添加脚本

public Transform dest;
    private NavMeshAgent agent;

    // Use this for initialization
    void Start ()
    {
        agent = GetComponent<NavMeshAgent>();
        agent.SetDestination(dest.position);
        agent.areaMask = -1 ^ 1 <<6;//第六个标签   
    }
    void SendMask(int mask)
    {
        agent.areaMask = mask;
    }
2019-09-07 15:21:14 wutaikun 阅读数 121
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4643 人正在学习 去看看 张刚

什么是导航网格系统?

前言:作为刚开始学习unity3d的菜鸟,将学习中觉得值得记笔记的地方分享给大家一起探讨,文中有理解错误的,勿怪哈!
unity3d 的NavMesh导航系统是一种用于动态物体自动寻路的技术。动态物体就是在游戏中可以运动的物体,一般是有生命的游戏角色,比如玩家英雄、怪物等。很多rpg游戏、实时对战游戏都是使用导航寻路,鼠标右击地图上的某点,游戏角色自动找出到达该地点的最佳路线,然后以一定速度前往该目的地,这就是导航寻路。静态物体就是游戏地图中位置和形状稳定的、可以形成导航网格的物体,常见的有地形、建筑物等。
unity3d的NavMesh导航系统的原理是根据A算法演变而来的,A算法是针对2D地图生成导航网格的算法,简单的说是把2D地形分成一个个矩形网格,然后按照广度优先算法,从起始点格子向周围的各自一层层探测,直到探测到目标点所在网格,比如
在这里插入图片描述
从A点导航到B点,首先将地图分成矩形网格,然后从A格子开始向周围的8个格子依次探索,如果周围的8个格子没有找到目标点B,则依次探索8个格子周围未探索的格子,直到找到B点所在格子,然后生成从A点到B点的路线。具体A算法可以自行查找资料。
unity3d的NavMesh所使用的导航网格算法源于A
算法,只不过为了扩展到三维世界的寻路,NavMesh将地图分成三角形网格(梯形也是由三角形组成),然后也使用广度优先算法从起始三角形一层层向外遍历,直到找到目标点所在的三角形,最后生成导航路线。
比如我们搭建一个简单场景
在这里插入图片描述
地面上放置4个立方体,地形plane和4个cube的static都选中Navigation Static,表示这5个对象都参与导航网格的烘焙,其中黑色的两个cube的Navgation Area选项设置为Not Walkable,表示障碍物,障碍物所在区域无法生成行走路线。其余的两个白色cube和地面都设置为Walkable,表示可以通行的区域。我们点击Bake选项卡右下角的Bake按钮对场景进行导航网格的烘焙,可以看到生成的导航网格。
在这里插入图片描述
如图,凡是可以通行的地方都生成了蓝色的导航网格。这张导航网格保存后将作为整个游戏场景的导航网格,在开始游戏后,挂载Nav Mesh Agent组件的游戏角色在使用导航寻路时会按照这张保存的导航网格进行寻路。注意,导航网格是提前烘焙好的静态的地图,即使在游戏中Navgation Static对象发生了变化(移动、变形、毁灭),导航网格也不变,比如事先烘焙一座桥为可行进的导航网格,在游戏中桥被毁坏了,使用导航时游戏角色依然认为桥是存在的,导航路线不变。如果游戏中出现非Navgation Static的对象挡住了导航网格,游戏角色依然认为没有阻挡,不会改变导航路线,只不过行进的路上会被挂载碰撞体的对象所阻挡。
接下来编辑Nav Mesh Agent组件,在场景中放置一个绿球代表玩家hero,放置一个小红球代表目的地。给hero球加上Nav Mesh Agent组件,然后编写脚本TestNavMesh.cs来开启导航系统的使用。代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class TestNavMesh : MonoBehaviour
{
    public Transform target;
    void Start()
    {
        if(target != null)
        {
            GetComponent<NavMeshAgent>().destination = target.position;
        }
    }
}

将TestNavMesh.cs放到hero球上作为脚本组件,然后将target球赋予target变量。接着运行游戏,即可看到绿球主动走到红球的位置,过程中虽有障碍物,但是导航路线自动避开了障碍物。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2019-09-08 00:57:43 wutaikun 阅读数 25
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4643 人正在学习 去看看 张刚

为什么要用导航网格系统?

前言:作为刚开始学习unity3d的菜鸟,将学习中觉得值得记笔记的地方分享给大家一起探讨,文中有理解错误的,勿怪哈!
我相信,许多同学刚开始接触unity3d,熟悉基本操作之后,都像我一样迫不及待地开始搭建一个自己的游戏场景,在游戏场景中畅游,享受一种创造世界的快感。当我们搭建好游戏场景后,要想在游戏中观赏我们的游戏地图,就不得不需要一个控制角色和摄像头移动的脚本。所以我们开始学习写的第一个脚本要么是通过wasd和方向键控制角色的脚本,要么是模仿RPG游戏,通过鼠标点击地图控制游戏角色走到指定位置的脚本。
当我学会写角色控制脚本后,再学习NavMesh导航网格这一章的时候,有一个疑问一直困扰我好久:我们既然可以通过一个简单的脚本就能控制角色移动,为什么需要用导航系统呢?下面我们就先搭建一个简单的场景,
在这里插入图片描述
场景中有一个Plane地板,一个绿色的坦克玩家,两个立方体障碍物。给坦克、两个立方体都加上刚体组件(Rigidbody),可以给两个立方体障碍物的Rigidbody组件勾选Is Kinematic,坦克不勾选,也可以反过来。如果坦克和障碍物都勾选了Is Kinematic,则坦克撞向障碍物时会穿过障碍物(穿模,相当于没有刚体效果),如果坦克和障碍物都不勾选Is Kinematic,则坦克撞向障碍物时会把障碍物推开。如果障碍物不勾选Is Kinemic,而且坦克不加刚体,坦克撞向障碍物时会穿模,但是会给障碍物一个力,障碍物会旋转个不停。这里模拟立方体障碍物是不能移动的,所以勾选Is Kinematic,坦克不勾选。接着给坦克编写一个鼠标控制移动的脚本MoveController.cs,代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveController : MonoBehaviour
{
    public float speed = 2.0f;
    private Vector3 targetPos;
    private bool isAvalaibleTarget = false;
     // Start is called before the first frame update
    void Start()
    {
        
    }
    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(1))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit = new RaycastHit();
            if (Physics.Raycast(ray,out hit))
            {
                if (hit.collider.name == "Plane")
                {
                    targetPos = hit.point;
                    targetPos.y = transform.position.y;
                    isAvalaibleTarget = true;
                }
            }
        }
        if (isAvalaibleTarget)
        {
            Vector3 direction = (targetPos - transform.position).normalized;
            Quaternion dirQua = Quaternion.LookRotation(direction, Vector3.up);
            transform.rotation = Quaternion.Lerp(transform.rotation, dirQua, 0.5f);
            transform.position += direction * speed * Time.deltaTime;
            if (Vector3.Distance(targetPos,transform.position) < 0.1f)
            {
                transform.position = targetPos;
                isAvalaibleTarget = false;
            }
        }
    }
}

将MoveController.cs脚本放到hero对象上,运行游戏,可以看到我们鼠标右击哪里,坦克就会转向走到哪里。当坦克撞向障碍物时会被挡住,然后物理引擎计算抖动和滑动,直到滑出障碍物阻挡范围,继续向鼠标点击的目标移动。
在这里插入图片描述
注意代码中的这一行,表示物体寻路时通过脚本修改transform控制的。
在这里插入图片描述

下面使用NavMesh导航系统进行寻路,控制坦克移动。
首先将地板Plane、两个立方体障碍物都标识为Navigation Static,参与导航网格的烘焙。地板Plane的Navigation Area设置成Walkable,表示可以通行,两个立方体障碍物设置成Not Walkable,表示不可通行。然后点击Bake选项卡的Bake,按钮进行导航网格的烘焙。
在这里插入图片描述
接着给hero添加Nav Mesh Agent组件。然后编写NavMeshController.cs脚本,代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class NavMeshController : MonoBehaviour
{
    public float speed = 2.0f;
    private Vector3 targetPos;
    private bool isAvalaibleTarget = false;
    // Start is called before the first frame update
    void Start()
    {
    
    }
    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(1))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit = new RaycastHit();
            if (Physics.Raycast(ray, out hit))
            {
                if (hit.collider.name == "Plane")
                {
                    targetPos = hit.point;
                    targetPos.y = transform.position.y;
                    isAvalaibleTarget = true;
                }
            }
            GetComponent<NavMeshAgent>().destination = targetPos;
        }
    }
}
    

将NavMeshController.cs挂载hero对象上,注意取消hero对象上之前的所有控制脚本。运行游戏,可以看到鼠标点击地面,坦克随即自动化寻路走到点击的位置,行走过程中自动避开障碍物(如果障碍物加了刚体,并且碰撞盒较大,在烘焙导航网格时障碍物区域太小,在使用导航寻路时,坦克经过障碍旁边仍然会擦边碰撞,这一点可以采取缩小坦克或者障碍物碰撞盒,或者干脆取消刚体组件,或者在烘焙导航网格时在Bake选项卡设置Agent Radius的值大一点等等措施解决)。
在这里插入图片描述

现在,我们知道了,简单脚本控制角色寻路是很直接地命令角色朝目的地走去,如果途中有阻挡,角色依然不改变方向地撞上去。而使用NavMesh导航系统则角色会先计算一条可行路线(即便没有可行路线,仍然会走到离目的地最近的地方),避开障碍物,走向目的地。如果你的场景设置成下面这样
在这里插入图片描述
或者更复杂的迷宫,你就能体会到如果使用简单控制脚本时,玩家角色七磕八幢走向目的地的难受了。当然了,使用unityd自带的NavMesh导航系统必然会收到系统本身的一些限制,比如寻路过程中的转身动作的,动画播放等很难去控制。自己写的控制脚本自由度就比较高了,你想怎么控制就怎么控制,模拟导航寻路,使角色寻路过程中避开障碍物也是可以自己实现的,比如使用射线探测障碍物等手段。

没有更多推荐了,返回首页