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