您的位置:首页 > 移动开发 > Unity3D

Unity寻路系统跟摄像机实战

2015-04-21 20:05 537 查看
这两天研究了一下unity的寻路系统跟摄像机的一些东西

在游戏中,我们经常会用到寻路这个功能,以前的做法多数是使用A*算法

而unity中自己带有了一套寻路系统供我们使用,关于这个这个用法,我们可以从《unity 4.x从入门到精通》的第九章了解到如何生成一个寻路网格

本文重点是展示这个寻路系统的使用效果,结合《unity 4.x从入门到精通》上摄像机相关的知识(185-189页),来做一个人物寻路,然后小地图显示场景效果

本文unity版本为4.6版本,用到的技术要点如下:

1.unity自带的寻路系统

2.理解鼠标点击2D屏幕,用射线方式映射到世界3D坐标,确定移动的目标点

3.摄像机画中画技术

4.摄像机跟随物体技术

5.UGUI的使用

好,现在我来一步步讲解我的制作过程

首先我们创建一个空的GameObject,用于装载地面,阻碍物,模拟人物等物体,

接着我们创建一个plane作为我们的地面,修改他的scale为10,1,10

然后我们创建一个sphere做作为我们的模拟人物,创建后,添加Nav Mesh Agent控件

创建三个cube作为我们的阻碍物,这三个cube需要设置为static,不然生成寻路网格的时候会无效

加一个平行光照到我们的plane上

创建一个点灯源,稍后作为我们鼠标点击位置的示意用

场景效果如下图所示



生成寻路网格点击Window->Navigation,在Object那里选择All后,直接点击Bake按钮生成就可以

生成后,会在你存放场景的目录下有一个跟场景名一样的文件夹,里面放着网格信息的



接着,我们用UGUI来建一个UI,它的右上角显示小地图的

直接点击GameObject->UI->RawImage来建立一个UGUI的UI系统,然后调整RawImage的大小为128X128

然后我们新建一个摄像机,命名为textureCamera

新建UGUI的Canvas下的Render Mode选Screen space overlay就可以了,意思就是覆盖在屏幕之上

为何我们要用RawImage,因为我们注意到,摄像机有一个叫做targetImage的成员参数,这个参数是用于存储摄像机映射场景画面到这个targetImage上去的

这个参数初始值为空,需要我们自己建立一个RenderTexture对象去传给它,设置了这个参数之后,这个摄像机的画面就不会自动合并到我们的屏幕上去了

需要我们用脚本控制显示这个targetImage才能看到这个摄像机原本看见的画面

我们就用此原理来达到制作小地图的效果

整个场景对象结构图如下



下面贴一下用到的脚本

1.角色控制脚本,主要接受鼠标点击,然后转换到世界坐标上去,然后通知人物走到那个位置

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {
private NavMeshAgent man;
public Transform pointLightPos;

// Use this for initialization
void Start () {
man = GetComponent<NavMeshAgent>();
if (null == pointLightPos)
{
pointLightPos = GameObject.Find("Point light").transform;
}
}

// Update is called once per frame
void Update () {
//man.SetDestination(targetPos.position);
//按下了鼠标左键,就发出射线
if (Input.GetMouseButtonDown(0))
{
//调用射线函数检测
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
//检测到碰撞就设置点光灯的位置
pointLightPos.position = new Vector3(hit.point.x,transform.position.y,hit.point.z);
man.SetDestination(hit.point);
}
}
}

}
把上面的playercontroller.cs绑定到player的物体对象上去,并拉点灯源到那个pointLisht去
另外这里说一下,我发现这个鼠标点击映射到世界坐标中主要是按Main Camera的坐标去映射的,其他的Camera要通过写特殊脚本的方式去映射

大家可以试试,这里mark一下

2.地图摄像机中的targertTexture替换脚本

using UnityEngine;
using System.Collections;

public class CameraController : MonoBehaviour {

private RenderTexture renderTexture;
Camera textureCamera;

// Use this for initialization
void Start () {
//创建一个临时的RenderTexture,给摄像机的targetTexture存储摄像机画面用
renderTexture = RenderTexture.GetTemporary(128, 128, 24, RenderTextureFormat.ARGB32);
renderTexture.isPowerOfTwo = false;
renderTexture.useMipMap = false;
//获取摄像机组件,然后设置targertTexture
textureCamera = GetComponent<Camera>();
textureCamera.targetTexture = renderTexture;
}

// Update is called once per frame
void Update () {

}
}


把这个脚本绑定到textureCamera上去

3.UGUI上显示小地图的控制脚本

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class ShowImage : MonoBehaviour {

private RawImage rawImage;
public Camera textureCamera = null;

// Use this for initialization
void Start () {
rawImage = GetComponent<RawImage>();
if (null == textureCamera)
{
textureCamera = GameObject.FindGameObjectWithTag("texturecamera").GetComponent<Camera>();
}
}

// Update is called once per frame
void Update () {
//直接使用摄像机的targetTexture替换
rawImage.texture = textureCamera.targetTexture;
}
}
把这个脚本绑定在UGUI中的RawImage中区

4.主摄像机设置跟随在人物后面,动态跟随

using UnityEngine;
using System.Collections;

public class CameraFollow : MonoBehaviour {

public GameObject player;
private Camera camera;

// Use this for initialization
void Start () {
camera = GetComponent<Camera>();
}

// Update is called once per frame
void Update () {
//计算摄像机位置
Vector3 newPos = player.transform.position + (-20.0f * player.transform.forward) + new Vector3(0.0f,20.0f,0.0f);
transform.position = newPos;
//设置摄像机的摄像方向为对着物品方向
transform.rotation = Quaternion.LookRotation(player.transform.position - transform.position);
}
}
把这个脚本绑定到Main Camera中区

好了最后看看我做的东西最后做到的效果







最后我上传一下这个项目的包,大家有需要可以下载来看一看,我是新手,有什么不足之处欢迎大家交流,下载地址为:
http://download.csdn.net/detail/a6627651/8617683
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息