纳金网
标题:
利用Unity3d中的自动寻路来为角色设置目的地
[打印本页]
作者:
wyb314
时间:
2012-11-16 10:02
标题:
利用Unity3d中的自动寻路来为角色设置目的地
不少游戏中,你只需在屏幕上单击一下,角色就可以向那个地方奔跑,然后到达目的地停了下来 ,Dota里面就是这样的 。今天,就让我们来实现这一功能吧。我们这次是借助Unity3d里面的自动寻路组件来实现这一功能,所以对此组件不熟悉的读者我希望您事先看一下这方面的资料,不会花你多长时间的。好了,让我们开始吧!
首先,我们得有一个工作目录,所以我们得新建一个工程,我把它命名为:TestNavMeshAgent,然后保存当前的Scene,给它一个名字:RobotNavMesh。接下来我们开始搭建我们的场景了。因为我不会做模型,所以像往常一样,我从别的工程里面抠出了一个角色:Robot,还是官方的CharacterAnimation这个工程里的一个机器人模型。我们得新建一个平面(用Cube做的)作为Robot落脚的地方,还是给这个平面一个颜色吧,并且加一个灯光吧。调节一下摄像机的位置与旋转角到一个比较合适的程度,就像下面这样:
我们接下来该烘焙平面,生成导航网格了。如果读者对此部分不是很熟悉,建议认真研究一下,也没什么难度,如果不熟悉英文,就到Unity圣典上看中文算了。
好了,我们开始烘焙场景了。选中我们的地面,然后打开Navigation窗口:Window->Navigation。勾选Navigation Static 这个选项,并且打开Navigation Layer下拉菜单,然后选择Default,最后单击Navigation窗口的右下角的Bake按钮。我们可以发现,Scene中的地面颜色发生了改变,如:
这就是导航网格生成后的场景。然后我们往Robot身上添加一个组件:NavMeshAgent,即:Unity菜单栏:Component->Navigation->Nav Mesh Agent。这个组件就是寻路系统的核心组件,我们接下来将利用这个组件来完成Robot的移动了。接下来我们必须写几个脚本,我写了3个脚本:RayCastPerFrame.cs, NavMeshController.cs, RobotNavAnimaiton.cs。RayCastPerFrame.cs的代码如下:
using UnityEngine;
using System.Collections;
public class RayCastPerFrame : MonoBehaviour {//这个脚本将要被附着到Robot身上
private RaycastHit hitInfo ;
void Update () {
if(Input.GetMouseButtonDown(1)){//当我们点击鼠标右键时,
Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out hitInfo);
//以摄像机为原点,向鼠标光标世界坐标点发射射线投射碰撞
}
}
public RaycastHit GetHitInfo()
{
return hitInfo;//得到碰撞信息
}
}
这个脚本比较简单,是专门获取射线碰撞信息hitInfo的。
NavMeshController.cs的代码如下:
using UnityEngine;
using System.Collections;
public class NavMeshController : MonoBehaviour {//此脚本将附着到Robot上
public RayCastPerFrame rcpf;//待会会将Robot拖拽到这个变量上,为的是直接访问Robot身上的RayCastFrame脚本。
private NavMeshAgent nma;//用于存储Robot身上附带的NavMeshAgent组件
void Start () {
nma = gameObject.GetComponent<NavMeshAgent>();
//实例化nma
}
void Update () {
if(!rcpf){
return;
}
RaycastHit hit = rcpf.GetHitInfo();//获取碰撞点
if (hit.transform)
{
nma.SetDestination(hit.point);//设置目的地位射线与平面的碰撞点
}
}
}
RobotNavAnimaiton.cs的代码如下:
using UnityEngine;
using System.Collections;
public class RobotNavAnimation : MonoBehaviour {//此脚本呢附着在Robot身上
private NavMeshAgent nma;//用于存储Robot身上附带的NavMeshAgent组件
void Start()
{
nma = gameObject.GetComponent<NavMeshAgent>();//实例化nma
animation.AddClip(animation["shoot"].clip, "shootUpperBody");
animation["shootUpperBody"].AddMixingTransform(transform.Find("mover/gun"));
animation["shootUpperBody"].AddMixingTransform(transform.Find("mover/roothandle/spine1"));
animation.wrapMode = WrapMode.Loop;
animation["jump"].wrapMode = WrapMode.Clamp;
animation["shoot"].wrapMode = WrapMode.Clamp;
animation["shootUpperBody"].wrapMode = WrapMode.Clamp;
animation["idle"].layer = -1;
animation["***n"].layer = -1;
animation.Stop();
}
void Update () {
if (nma.remainingDistance != 0)//如果导航代理还没有到达目的地,则播放跑的动画。
{
animation.CrossFade("***n");
//animation["***n"].speed = Mathf.Sign(Input.GetAxis("Vertical"));
}
else //否则播放站立的动画
{
animation.CrossFade("idle");
}
if (Input.GetButtonDown("Jump"))
{
animation.CrossFade("jump", 0.3f);
}
if (Input.GetButtonDown("Fire1"))
{
if (animation["***n"].weight > 0.5f)
animation.CrossFadeQueued("shootUpperBody", 0.3f, QueueMode.PlayNow);
else
animation.CrossFadeQueued("shoot", 0.3f, QueueMode.PlayNow);
}
}
}
这个脚本涉及到了动画的混合,现在就先将就着看吧,我或许会在接下来的日子里写出我的第四篇有关与动画方面的文章,有兴趣的可以留意一下。
最后,我们将这三个脚本绑定在Robot上面,并且在Hierarchy面板中将Robot拖拽到NavMeshController这个脚本中的Rcpf这个选项上,如下图:
寻路时的状态,已经达到了我们想要的效果。
我们还可以家一个障碍物,这个就留给读者自己添加吧。可是你有没有注意到一点,RayCastPerFrame .cs这个射线检测的脚本是每帧都在检测,NavMeshController.cs也是每帧都在获取碰撞信息,每帧设定目的地。这个就相当消耗性能。那么这个问题就留给读者自行解决吧!我提个思路,比如说当距离上次检测碰撞信息的时间超过0.1s时设置导航网格代理的目的地,这个应该是很好实现的。
我把工程给贡献出来,有兴趣的读者不妨下载下来研究一下。
TestNevMeshAgent.rar
2012-11-16 10:02 上传
点击文件名下载附件
0 Bytes, 下载次数: 253
作者:
王者再临
时间:
2012-11-16 15:56
寻路系统很少有这方面的介绍,谢谢了!!
作者:
所罗门封印
时间:
2012-11-16 23:23
记得貌似有个啥专业A星寻路的插件。
作者:
其实我是神
时间:
2012-11-17 09:52
好东西好东西!好东西好东西!
作者:
比巴卜
时间:
2012-11-21 09:25
来围观!!!
作者:
冰点
时间:
2012-11-23 16:05
wed 3d 纳金网
作者:
王者再临
时间:
2012-11-24 02:15
学习中!
作者:
may
时间:
2012-11-24 03:01
lZ的回复很不错,支持!
作者:
lhg22254
时间:
2012-12-21 11:52
认真学习中
作者:
may
时间:
2012-12-24 05:25
来支持一下楼主的帖子哦
作者:
王者再临
时间:
2012-12-27 19:33
学习了,虽然还是有难度,谢谢楼主的用心
欢迎光临 纳金网 (http://rs.narkii.com/club/)
Powered by Discuz! X2.5