来自:http://www.narkii.com/club/forum.php?mod=viewthread&tid=269146&highlight=Unity%E9%87%8C%E9%9D%A2%E7%9A%84%E8%87%AA%E5%8A%A8%E5%AF%BB%E8%B7%AF

众所周知,自动寻路是所有游戏的一个难点,属于AI(人工智能)的范畴。一个游戏的AI的设计是否足够完美,可能决定了这个游戏的命运。然而自动寻路就是AI中的一个十分重要的分支,其算法异常复杂。然而unity3d中提供了一套非常成熟的组件来为我们解决这一难题。今天,我们就来一起欣赏一下Unity3d自带的自动寻路系统。

我们在学习一个陌生的知识时,免不了要记一些令人烦恼的概念,自动寻路也是一样的。但是记东西也是有技巧的,我认为我们应该先看到一点惊喜再学东西,这样兴趣有了,学东西就不那么抵触了。所以我现在先列举举一个简单的例子,记住,先不要思考为什么我要这样做,如果你是初次学习这个自动寻路的话最好这样,不然你会走很多弯路的。我们需要新建一个工程,将其起名为:NavMeshProject。然后我们可以制作场景了。
        像往常一样,先做一个地面,这里我用的是Cube。然后我将我们的朋友Robot也请来了,看这:

是不是很帅啊!我特意加了个灯光,给地面换了个柔和的颜色,看起来就不那么单调了。然后我们保存一下整个场景,该场景取名为:TestNavgation1。
下面我来烘焙场景,但是记住,先不要想为什么。Unity3d编辑器的菜单下:Window->Navigation,这是我们可以发现编辑器的某一部分出现了一个Navigation窗口,如:

请注意一下此图的右下角的一个Bake按钮。
在Hierarchy下选中Plane(就是那个地面),然后我们在Navigation面板中的Object选项卡下找到Navigation Static复选框,勾选它,然后点击Navigation面板右下角的Bake按钮:

此时我们可以发现Project面板下面多出了一个文件夹,且此文件夹出现了一个子文件NavMesh:

并且Scene窗口中的地面上出现了一下变化:

然后我们跟robot添加一个组件:NavMeshAgent。具体做法是 :  在Hierarchy面板下选中robot,然后在Unity3d菜单下:Component->Navigation->NavMeshAgent,你会发现robot身上出现了一个类似胶囊体碰撞器的绿色线框的包围体,调节一下盖NavMeshAgent组件中的一些参数:Height,BaseOffset等,如图:

最后我们该编写脚本了。我还是新建一个文件夹:Scripts。然后编写两个脚本:
脚本一,专门设置导航网格代理的目的地的:

using UnityEngine;
using System.Collections;

public class NavMeshMove : MonoBehaviour {

public Transform[] NavMeshTransforms;//导航网格的目的地组。

private NavMeshAgent nma;//Robot的导航网格代理

void Start () {
        if(NavMeshTransforms == null)
        {
            return;
        }
    nma = gameObject.GetComponent<NavMeshAgent>();
            nma.SetDestination(NavMeshTransforms[0].position);//初始时刻设置的导航网格代理的目的地
}

void Update () {

if(nma.remainingDistance == 0){
            //当导航网格代理到达了目的地时,更换目的地,且是随机的更换
            nma.SetDestination(NavMeshTransforms[Random.Range(0,NavMeshTransforms.Length)].position);
        }
   }
}

脚本二,是专门为导航网格代理编写的动画控制脚本:

using UnityEngine;
using System.Collections;

public class NavNeshAnimation : MonoBehaviour {

public float***nAnimaitonSpeed = 4.0f;//定义最大的跑步速度,一般为导航网格代理的速度
    public float speedThreshold = 0.1f;//定义动画从idle***n过渡的临界速度

private string loadAnimation = "load_Idle";//定义需要执行的协同函数名
    private NavMeshAgent nma;//定义导航网格代理

IEnumerator Start () {
    nma = gameObject.GetComponent<NavMeshAgent>();
        AnimationSetup();//简单的设定一下动画。

while(Application.isPlaying) {
            yield return StartCoroutine(loadAnimation);//执行协同函数
    }
    }

IEnumerator load_Idle() 
    {
        do{
            UpdateAnimationBlend();
            yield return null;
            
        }while(nma.remainingDistance == 0);

loadAnimation = "load_Run";
        yield return null;
    }

IEnumerator load_Run()
    {
        do
        {
            UpdateAnimationBlend();
            yield return null;

} while (nma.remainingDistance != 0);

loadAnimation = "load_Idle";
        yield return null;

}

void AnimationSetup() 
    {
        animation["idle"].layer = 1 ;
        animation["***n"].layer = 1;
        animation.SyncLayer(1);

animation.CrossFade("idle", 0.1f, PlayMode.StopAll);
    }
    
    void UpdateAnimationBlend() 
    {
        Vector3 velocityXZ = new Vector3(nma.velocity.x,0.0f,nma.velocity.z);
        float speed = velocityXZ.magnitude;
        animation["***n"].speed = speed /***nAnimaitonSpeed;

if (speed > speedThreshold)
        {
            animation.CrossFade("***n");
        }
        else {
            animation.CrossFade("idle");
        }
    
    }
}

我们将这两个脚本绑定到robot身上,然后我们在Hierarchy面板中新建一个空的GameObject,重命名为:NavMeshPoint,并且新建5个spere作为它的子对象被其管理,如下:

然后将这5个spere分开到Plane上的不同位置,如下:

选中robot,然后在Inspector下的NavMeshMove脚本上设置NavMeshTransforms的个数为5,并且将那5个spere分别拖拽到相应的位置,如下:

好了,我们可以运行一下工程,看一下效果,这里只截了部分图片:

从图中我们可以看出,我们的robot在不断的跑步,每次跑到目标点之后停下来,然后转身朝向下一个目标点,如果工程没有停止,那么它周而复始的循环下去,这对于编写NPC的AI很有帮助。

Unity里面的自动寻路(一)的更多相关文章

  1. Unity里面的自动寻路(二)

    接着我的 上一篇自动寻路文章,这一次我们就来学习一下与自动寻路有关的组件吧.Unity中与自动寻路相关的组件主要有两个:NavMeshAgent (  又称导航网格代理 ),Off Mesh Link ...

  2. Unity 3D 中自动寻路 和 跟随转向 探析

    这里主要讲三个函数 , 一个自动跟随函数 和 两个指向旋转函数 , 这三个函数在游戏角色创建过程中会经常用到: 这个是跟随函数 和 欧拉角旋转函数 public class GensuiZhixian ...

  3. Unity自动寻路Navmesh之高级

    隔离层自动生成寻路网格 (源码scene1.unity) 1.创建Plane实例P1,P2,两者之间出现一条鸿沟.直接控制角色位移是无法通过的. 2.打开Navigation窗口,分别选中P1,P2, ...

  4. Unity手游之路<八>自动寻路Navmesh之入门

    http://blog.csdn.net/janeky/article/details/17457533 在的大部分mmo游戏都有了自动寻路功能.点击场景上的一个位置,角色就会自动寻路过去.中间可能会 ...

  5. Unity手游之路<九>自动寻路Navmesh之高级主题

    http://blog.csdn.net/janeky/article/details/17492531 之前我们一起学习了如何使用Navmesh组件来实现最基本的角色自动寻路.今天我们再继续深入探索 ...

  6. Unity中使物体自动寻路的方法

    在做一个FPS游戏时,需要敌方自动找到玩家方位并向玩家移动,在查找资料(并走了不少坑)后,我试了三个方法,经测试,这三个方法都能实现自动寻路功能. 方法一:使用Mathf.Lerp()方法 代码很简单 ...

  7. Unity手游之路自动寻路Navmesh之高级主题

    http://blog.csdn.net/janeky/article/details/17492531 之前我们一起学习了如何使用Navmesh组件来实现最基本的角色自动寻路.今天我们再继续深入探索 ...

  8. Unity手游之路自动寻路Navmesh之入门

    http://blog.csdn.net/janeky/article/details/17457533 现在的大部分mmo游戏都有了自动寻路功能.点击场景上的一个位置,角色就会自动寻路过去.中间可能 ...

  9. Unity自动寻路入门指南

    所有用于成为NavMesh的网格都必须被指定为 Navigation Static . 方法如下,选中GameObject,然后在菜单栏的[Window]-[Navigation]-[Object]- ...

随机推荐

  1. 转:LinkedHashMap使用(可以用来实现LRU缓存)

    1. LinkedHashMap概述: LinkedHashMap是HashMap的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap. LinkedH ...

  2. 【ZOJ4061】Magic Multiplication(构造)

    题意:定义一个新运算为两个数A,B上每一位相乘,然后顺次接在一起,现在给定结果C和原来两个数字的长度,要求恢复成原来的数字A,B 若有多解输出A字典序最小的,A相同输出B字典序最小的,无解输出Impo ...

  3. BS4爬取豆瓣电影

    爬取豆瓣top250部电影 ####创建表: #connect.py from sqlalchemy import create_engine # HOSTNAME='localhost' # POR ...

  4. Centos7部署Open-Falcon监控

    参考博主:努力哥完成 一.Open-Falcon介绍 1.监控系统,可以从运营级别(基本配置即可),以及应用级别(二次开发,通过端口进行日志上报),对服务器.操作系统.中间件.应用进行全面的监控,及报 ...

  5. Razor 常用方法

    结合wdate使用 //WdatePicker控件时间限制 @Html.TextBoxFor(model => model.BookingStart, new { @onClick = &quo ...

  6. Javascript中call、apply函数浅析

    call/apply函数作用其实就是改变this的取值,有一句话是:谁调用的这个方法那方法里的this就是指谁,而有时我们会需要改变this值,所以call/apply就能派上用场. 下面我写个方法来 ...

  7. (转)Ubuntu安装g++-4.8

    sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install g++-4.8 ...

  8. 阿里云服务器,tomcat启动,一直卡在At least one JAR was scanned for TLDs yet contained no TLDs就不动了

    项目在本地是可以成功运行的,网上看到一堆各式各样的解决办法感觉都不适合我,于是绝望的删webapps,重新上传,一直不行. 重复了第3次还是第4次,居然就好了,这是什么操作.

  9. 中矿大新生赛 G 甄总搬石头【优先队列/哈夫曼/贪心】

    时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 32768K,其他语言65536K64bit IO Format: %lld 题目描述 https://www.nowcoder.com/ ...

  10. Codeforces 935E Fafa and Ancient Mathematics(表达式转树 + 树型DP)

    题目链接  Codeforces Round #465 (Div. 2) Problem E 题意  给定一个表达式,然后用$P$个加号和$M$个减号填充所有的问号(保证问号个数等于$P + M$) ...