2019-02-21 12:49:19 qq_43667944 阅读数 49
               

2016/09/07更新

NavMeshAgent 默认是会有碰撞效果的,就是说 玩家和玩家是会有碰撞,不能重叠。

这是因为NavMeshAgent 默认设置了体积,而且开启了障碍物检测。


只要把 Radius 改成0,或者关闭 Obstacle Avoidance,人物就可以重叠了。


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Unity3d中的寻路,可以使用AStarPath 寻路插件。现在也可以使用Unity自带的 Navigation 功能来做。

来做一个例子:


上面的图片中,Cube 是阻碍物体,球 是代表玩家,要寻路。


设置Cube为不可通过物体

首先我们点击Window - Navigation 窗口,然后选中4个Cube,按照下图设置这4个Cube为不可通过,然后烘培



设置地面为可通过,然后烘培


我们给圆球也就是我们的主角加上控制脚本

using UnityEngine;using System.Collections;public class findpath : MonoBehaviour {    public NavMeshAgent agent;    Vector3 point;    Ray aray;    RaycastHit ahit; // Use this for initialization void Start () {  }  // Update is called once per frame void Update () if (Input.GetMouseButtonDown(0)) {        aray = Camera.main.ScreenPointToRay(Input.mousePosition);        if (Physics.Raycast(aray,out ahit))        {            point = ahit.point;        }        agent.SetDestination(point); }  }}

达到圆球朝鼠标点击的地方寻路效果转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn


注意到在使用NavMesh的时候,发现 NavMeshAgent 的物体,是不能移除到 NavMesh 范围外的。


如果NavMeshAgent 在 NavMesh 范围之外,也会被自动的设置到NavMesh里面去。

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn


而且当执行一次寻路之后,如果我们改变Cube的位置,Cube又会寻路回到原来的目的地,感觉就像是这一次寻路没有完成。

这就需要我们增加判断,在Cube 移动到目的地之后,结束这一次的寻路。

代码修改如下

using UnityEngine;using System.Collections;public class NewBehaviourScript : MonoBehaviour {    public NavMeshAgent agent;    Vector3 point;    Ray aray;    RaycastHit ahit;    bool mDoFindPath = false;    // Use this for initialization      void Start()    {            }    // Update is called once per frame      void Update()    {        if (Input.GetMouseButtonDown(0))        {            aray = Camera.main.ScreenPointToRay(Input.mousePosition);            if (Physics.Raycast(aray, out ahit))            {                point = ahit.point;            }            agent.SetDestination(point);            mDoFindPath = true;        }        //增加已经寻路到目的地的判断,然后结束这一次寻路        if(mDoFindPath && !agent.pathPending&& agent.remainingDistance !=Mathf.Infinity && agent.pathStatus==NavMeshPathStatus.PathComplete && agent.remainingDistance<=agent.stoppingDistance)        {            Debug.Log("NavMeshAgent Pathfinding End");            mDoFindPath = false;            agent.ResetPath();         }    }}

主要是这个函数,清除这一次的寻路

NavMeshAgent.ResetPath();

比如在游戏寻路的过程中,我们可以中断寻路,自己操作,就可以调用。

现在寻路之后可以随意拖动了转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn




我们在玩3D游戏的时候,一般游戏里都有一个脱离卡死的按钮。

这是因为在玩游戏的过程中,可能会有各种原因,导致玩家走到地图之外,比如穿墙了,穿地了,一直往下面掉。点脱离卡死,就能重置玩家的位置。


上面说了,如果Cube 在 NavMesh 范围之外,那么运行游戏之后,Cube 会自动移动到 NavMesh 的范围内。

这是Cube 的 NavMeshAgent 产生的效果。


但是如果Cube离NavMesh比较远的话,就没有这个效果了

并且产生了一个警告。

Failed to create agent because it is not close enough to the NavMesh

意思就是说,Cube 离 NavMesh 范围外太远了,创建 NavMeshAgent 失败了……


这样的话,依靠NavMeshAgent ,是达不到 脱离卡死的目的的,距离稍微远点就不给力了。

这个时候只好自己到 NavMesh 中找一个点,然后把玩家 移动到这个点。

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

代码修改如下:

using UnityEngine;using System.Collections;public class NewBehaviourScript : MonoBehaviour{    NavMeshAgent agent = null;    Vector3 point;    Ray aray;    RaycastHit ahit;    bool mDoFindPath = false;    // Use this for initialization      void Start()    {        agent = gameObject.AddComponent<NavMeshAgent>();    }    void OnGUI()    {        if (GUILayout.Button("脱离卡死"))        {            //寻找导航网格上,距离玩家最近的点,然后把玩家设置为点的坐标,就脱离卡死了。            NavMeshHit tmpNavMeshHit;            if (NavMesh.SamplePosition(transform.position, out tmpNavMeshHit, 10000f, NavMesh.AllAreas))            {                transform.position = tmpNavMeshHit.position;                agent.enabled = false;                agent.enabled = true;            }        }    }    // Update is called once per frame      void Update()    {        if (agent == null)        {            return;        }        if (agent.isOnNavMesh == false && agent.isOnOffMeshLink == false)        {            return;        }        if (Input.GetMouseButtonDown(0))        {            aray = Camera.main.ScreenPointToRay(Input.mousePosition);            if (Physics.Raycast(aray, out ahit))            {                point = ahit.point;            }            agent.SetDestination(point);            mDoFindPath = true;        }        //增加已经寻路到目的地的判断,然后结束这一次寻路        if (mDoFindPath && !agent.pathPending && agent.remainingDistance != Mathf.Infinity && agent.pathStatus == NavMeshPathStatus.PathComplete && agent.remainingDistance <= agent.stoppingDistance)        {            Debug.Log("NavMeshAgent Pathfinding End");            mDoFindPath = false;            agent.ResetPath();        }    }}

效果



关于 OffMeshLinks

在游戏的场景中,可能会出现两个 Mesh 没有连在一起的情况。这个时候寻路会被中断。

Unity 提供了 OffMeshLinks 给我们使用,字面上的意思就是,分离  Mesh 的连接器。

只要提供一个 Start 和一个 End ,两个Mesh 就可以连接起来。


首先搭建下面的场景


并添加两个Cube,一个作为起点 Start,一个作为终点 End


然后在作为Player的Cube上再添加一个 OffMeshLink,并把 起点、终点的Cube 拖过去


然后Bake,在 Start 和 End 之间,生成了一条曲线,把 分离的两个 地板 连接起来

转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

运行游戏测试


测试工程下载:

http://pan.baidu.com/s/1pLD3HEj


           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

2018-05-31 18:28:23 q764424567 阅读数 4260

#Unity3d 寻路插件APathfinding学习与研究(一)



##参考资料
1.A* Pathfinding Project
2.从A寻路项目开始
3.[Unity3D插件系列]-A
Pathfinding Project 学习(一)



##下载链接
https://arongranberg.com/astar/download
https://pan.baidu.com/s/1-nUJxwR0GOa9UfN9YuVZ1Q



##从A寻路项目开始
寻路就是寻找A点和B点之间的最佳路径,这就是A*路径发现项目所做的,在本教程中,您将学习如何在新场景中设置项目,并在避免障碍的同时获得一个简单的AI移动。

这个AI你将写将不会很先进,它只是最低数量的代码,以获得移动和跟随一条道路。如果您想要更高级的人工智能,您可以扩展本教程中将要编写的脚本,或者使用(或扩展)AIPath或里奇包中包含的脚本(见第2部分,RichAI组件的基本用法)。



##概述

  1. A*Pathfinding插件的核心脚本就是AstarPath.cs脚本,它是场景中使用路径查找的组件。它是其他脚本的基础,负责生成寻路图形,并调整所有设置
  2. AstarPath.cs脚本只能在场景中存在一个,不能重复
  3. AstarPath.cs脚本可以在菜单栏->Components–>Pathfinding–>Pathfinder上找到。
  4. 第二个重要的组件是Seeker.cs组件,附加在需要使用路径查找的游戏对象上,例如AI
  5. 为了能让寻路的对象移动,需要添加脚本,这个移动的脚本可以自己编写,也可以用已经写好的移动脚本(AIPath, RichAI, AILerp)
  6. 处理路径平滑的脚本SimpleSommthModifier.cs,处理之后路径平滑或者简化一些
    ##首先是场景准备
  7. 先创建一个Panel,让其坐标位于(0,0,0)上,然后x轴、z轴扩大10倍,y轴不变
    这里写图片描述
  8. 再创建几个Cube,设置成障碍物
    这里写图片描述
  9. 接着设置Tag Edit->Project Settings->Tags&Layers
    这里写图片描述
    一个Tag设置成Ground->地面
    一个Tag设置成Obstacle->障碍物
    将Planel的Tag设置成Ground
    将创建的一个Cube障碍物设置成Obstacle
    这里写图片描述这里写图片描述
    ##现在我们来添加寻路网格
    创建一个新的GameObject,命名为“A*”,向其添加“AstarPath”组件(菜单栏->Components->Pathfinding->Pathfinder)。
    这里写图片描述这里写图片描述
    Width跟Depth设置网格的长度和宽度,由于跟Unity的单位是一样的,设置成100*100就行了
    NodeSize节点的宽度,设置成1就行了
    MaxClimb可以爬升的最大高度
    MaxSlope可以爬升的最大斜度
    Erosion iterations 这个就是障碍物避让的设置,如果寻路的时候穿过障碍物的话就可以把这个设置大一些
    这里写图片描述
    ##添加Ai
    这里写图片描述
    添加一个胶囊体,添加移动脚本让它移动
    这个时候有两种选择,1就是自己编写脚本,更能理解这个脚本的运行过程
    2就是使用已经写好的脚本AIPath, RichAI and AILerp
    AIPath脚本可以用于任何图形,而RichAI主要用于基于Navesh的图形。虽然AIPathRichAI脚本松散地遵循路径,但AILerp脚本使用插值非常精确地沿着路径移动,但可能不是以最现实的方式。你用哪一个取决于你的游戏。不同的脚本在不同的示例场景中使用,您可以查看它们的不同之处。


    在这个案例中,我们可以添加AIPath脚本,这个组件只是一个非常简单的助手脚本,它将告诉AIPath脚本移动到特定的位置。将来,您可能会用自己的游戏特定脚本来替换这个脚本。


    添加AIDestinationSetter组件,有一个名为“Target”的字段,将前面创建的“Target”GameObject分配给这个字段。
    这里写图片描述
    ##平滑
    OK,对象是不是开始朝着目标点移动了。是不是感觉有什么不对劲,对,路径怎么歪歪曲曲的
    这里写图片描述
    这个时候就要添加光滑组件了
    给对象添加上这个组件
    菜单栏–>Components–>Pathfinding–>Modifiers–>Simple Smooth
    现在再按下播放,路径应该看上去更流畅,正如我们所希望的。
    这里写图片描述
    OK。这次的学习就到这里吧,后续会有更新的。
    有什么不对的请大家给我指正出来,谢谢。。。
2016-05-10 17:25:36 prcfiona 阅读数 4246

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;
    }
2017-08-01 18:49:46 u010707274 阅读数 2120

Unity教程之-Unity3d自带寻路Navmesh

                <p>&nbsp;</p>

前面的文章《Unity教程之-Unity3d自动寻路功能介绍演示》我们学习过unity3d的自动寻路,最近收到有些朋友的反馈,关于unity3d的寻路的介绍还不是太深入,那么下面我们再来看下Unity3d自带寻路Navmesh:

自带寻路Navmesh的三大组件:

1.Nav Mesh Agent:主要挂在寻路物体上

2.Off Mesh Link:实现区域转移功能(例如,有时不一定只是在地面上进行寻路,可能有些高高的平台,平台与地面是不相连的,使用该组件可以跳到平台上)

3.Nav Mesh Obstacle:主要挂在障碍物上

一、基础

1.选中静态对象,勾选Navigation Static

2.Window/Navigation,弹出Navigation视图,点击右下角的Bake按钮生成导航网格

3.在Bake选项卡中调整参数

4.新建一个胶囊体,Component/Navigation/Nav Mesh Agent,添加导航组件

5.为胶囊体添加脚本

1
2
3
4
5
6
7
8
9
10
11
using UnityEngine;
using System.Collections;
 
public class FindObj : MonoBehaviour {
 
public Transform targetObj;
void Start ()
{
GetComponent<NavMeshAgent>().destination = targetObj.position;
}
}

二、其他功能

1.设置掉落点

a.选中所有静态对象,在Navigation视图的Object标签页下勾选OffMeshLink Generation

b.在Navigation视图的Bake标签页设置Drop Height,点击右下角的Bake按钮

2.跳跃功能

a.添加两个对象,分别为start point和end point

b.对于start point,Component/Navigation/Off Mesh Link,为该组件设置好Start和End

c.Bake后即可看到连接路径,如果看不到可以调整Bake标签页的Step Height

d.新建一个胶囊体,Component/Navigation/Nav Mesh Agent,添加导航组件,添加上面的导航脚本

如果希望上升过程丰富一些,比如播放一个爬梯或者飞行的动作,那么完全可以通过脚本来自行控制。

首先需要放弃勾选行进物体Nav Mesh Agent组件下的Auto Traverse Off Mesh Link选项,然后编写相应脚本来实现移动过程。在脚本中通过访问NavMeshAgent.isOnOffMeshLink成员来判断是否到达起点或终点,如果到达则访问NavMeshAgent.currentOffMeshLinkData成员来取得起点和终点的信息,最后实现自己的移动过程。完成移动后需要调用NavMeshAgent.CompleteOffMeshLink()来结束手动过渡过程

3.为网格分层

在Navigation视图下的Layers标签页可以设置层,Object标签页可以为物体指定层,Nav Mesh Agent组件的NavMesh Walkable可以指定可行走的层

4.动态更改可行进层

关于walkableMask:

Built-in Layer 0 对应的 walkableMask 为1

Built-in Layer 1 对应的 walkableMask 为2

Built-in Layer 2 对应的 walkableMask 为4

User Layer 0 对应的 walkableMask 为8

User Layer 1 对应的 walkableMask 为16

如此类推,即是walkableMask为2的(n-1)次方

当设置walkableMask 为-1时,表示所有层都能通过

当设置walkableMask 为0时,表示所有层都不能通过

当设置walkableMask 为1时,表示只有Built-in Layer 0层能通过

当设置walkableMask 为2时,表示只有Built-in Layer 1层能通过

当设置walkableMask 为3时,表示只有Built-in Layer 0和Built-in Layer 1层能通过(3 = 1 + 2)

当设置walkableMask 为8时,表示只有User Layer 0层能通过

可以通过查看Nav Mesh Agent组件的NavMesh Walkable看到设置walkableMask后的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using UnityEngine;
using System.Collections;
 
//该脚本挂在桥上,桥设置为User Layer 0的那个层
public class ChangeMovable : MonoBehaviour {
 
public Transform moveObj;//寻路的物体
public float timer = 0f;
 
void Start ()
{
if (moveObj != null)
{
moveObj.GetComponent<NavMeshAgent>().walkableMask = 0;
renderer.enabled = false;
}
}
 
void Update ()
{
timer += Time.deltaTime;
if (timer > 2f)
{
moveObj.GetComponent<NavMeshAgent>().walkableMask = -1;
renderer.enabled = true;
}
}
}


5.Nav Mesh Obstacle组件(动态路障)

为路障挂上该组件,当该组件enable为true时,不可通过,否则可以通过

该方法与设置可行进层的区别:

使用可行进层时,动态物体会在中断处暂停行进而等待新的路径出现后再继续行进,意味着在暂停的时候,物体的加速度为0;

而使用动态路障时,物体将不会暂停,而是一直在运动并试图绕过障碍来向目标点接近,意味着物体保持着一个加速度。

6.防止一群寻路的物体围住目标点:

设置Nav Mesh Agent组件中的Obstacle Avoidance Type为None,即可以让寻路物体互相穿过,好了,本篇unity3d教程到此结束,下篇我们再会!

 

2017-01-07 18:31:39 grf123 阅读数 1731

Unity3D中自动寻路的功能:

概述:

别人写的教程,非常详细,细节我就不赘述了。只写一些自己的总结:

1. 什么是导航网格:

“导航网格”,规定了使用自动寻路的GameObject所能或者不能通过的地方。

2. 如何生成导航网格:

菜单栏: Window——Navigation,打开导航网络控制面板。

选择想要生成网格的游戏物体,比如一个Plane,在”导航网格控制面板“中将“Navigation Static”打钩,点击右下角的Bake,烘焙路径,则可以看到自动生成的区域。Navigation Area则决定了这个区域是Walkable还是not Walkable或者是Jump。

3. 如何应用导航网格:

在自己的Player上添加一个“Nav Mesh Agent”组件,这个组件实现了自动寻路的功能,可以看做是一个封装。设计者只要使用这个组件就好了,具体可以看官方说明。

举个例子:

using UnityEngine;
using System.Collections;

public class SetHeroDes : MonoBehaviour
{
    public Transform ds;//用来确定目的地坐标的游戏物体的Transform
    private Vector3 origin;//存储导航网格代理的初始位置
    private NavMeshAgent nma;//存储导航网格代理组件

    void Start()
    {
        nma = gameObject.GetComponent<NavMeshAgent>();   //取得导航网格代理组件
        origin = transform.position;     // 存储一下这个脚本所挂载游戏物体的初始位置
        nma.SetDestination(ds.position); // 关键点:操作NavMeshAgent组件,设置自动寻路的目标位置为我们通过ds所指定的点。
    	}
}


把这个脚本挂到想要自动寻路的游戏物体,并指定目标位置游戏物体。

简单粗暴有木有?

nma.SetDestination(ds.position);

这句代码设置后,所挂载该脚本的游戏物体就开始依据我们通过Bake生成的导航网格自动寻路了。这个过程中,会自动绕过障碍物(通过Bake将这类游戏物体烘焙为not walked)。

4. OffMeshLink是什么?

按照我的理解,这个组件提供了不同的高度和导航网格中断的处理方案,详情看教程吧。


下面是别人教程的地址,非常详细:

有些教程里面的素材如果没有,通通用cube代替,学到东西才是真的。我看这些教程时,由于是几经转载,都看不到图的,就自己随便弄个cube,Metrial之类的搞完再说。


Unity里面的自动寻路(一)

Unity里面的自动寻路(二)

unity自带寻路Navmesh入门教程(一)

unity自带寻路Navmesh入门教程(二)

unity自带寻路Navmesh入门教程(三)


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