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

unity 通过摄像机模拟实现小地图

2014-04-30 16:11 1526 查看
unity中小地图的应用很广泛,目前多采用两种方式。

1、在unity俯视角下通过截图截取小地图背景图片,如图所示;

优点就是简单便捷,缺点是小地图高、宽需要确定不能通随意改变、不能做一些镜头特效例如缩放地图等。



2,、通过摄像机投影到texture上,通过GUI直接绘制出来。

缺点是操作步骤相对繁琐、优点是小地图是实时投影绘制可以通过脚本控制各种视角特效。



下面就对第二种方式做一个简单的实例,并详细列出操作步骤及相关程序代码。

小地图功能描述:

1、通过摄像机动态投影地图俯视图作为小地图背景。

2、小地图上可标注游戏对象(通过设置“Tag”标签来自动检索所有待标注游戏对象)

3、小地图上显示当前视角对象位置、旋转角度

4、小地图上单击鼠标左键,移动视角位置

5、动态设置小地图屏幕布局(仅实现右上角布局、左下角布局)

实际运行效果图如下



通过摄像机动态投影地图俯视图作为小地图背景

步骤一:在Hierarchy中添加第二个摄像机,名称为"TopCamera"





步骤二:在资源面板中新建“Render Texture”,命名“miniMap”





步骤三:在Hierarchy选中“TopCamera”,设置Target Texture为刚才新建的”miniMap“



步骤四:设置”TopCamera“,Transform--》Position--x坐标、y坐标、z坐标均为0



其它算法实现思路:

TopCamera通过程序自动投影全幅地图,设置TopCamera位于地图中央,调整摄像机属性”Field of view“,如图



TopCamera.transform.Translate(new Vector3(terrionWidth/2,200,terrionHeight/2),Space.World);// 200设置摄像机Y具备一定高度,
TopCamera.transform.Rotate(new Vector3(90,0,0),Space.Self);// 调整摄像机为俯视角度


待标注物体世界坐标如何换算到小地图中坐标

通过WorldToScreenPoint把世界坐标换算为屏幕坐标,计算该点屏幕坐标X、Y占全屏宽、高比例;

通过宽、高比例计算该点在小地图绘制点。

下面完整代码:

using UnityEngine;
using System.Collections;

public enum miniMapPosition{
右上角,左下角
}

public class miniMap : MonoBehaviour {
public float terrionHeight=0;// 场景高度
public float terrionWidth=0;// 场景宽度
public Camera cameraMap;// 投影地图摄像机
public Camera cameraMain;// 主摄像机
public Texture image;// 投影地图材质
//public Transform target;// 标注对象位置
public string targetTag;// 标注对象Tag
public Texture point;// 标注图标
public Texture cmTexture;// 主摄像机图标
public float miniMapW = 128;
public float miniMapH = 128;
public miniMapPosition mmPosition;

// Use this for initialization
void Start () {
if (terrionWidth!=0&&terrionHeight!=0)
{
// 设置顶层摄像机位置,投影实景地图
cameraMap.transform.Translate(new Vector3(terrionWidth/2,200,terrionHeight/2),Space.World);
cameraMap.transform.Rotate(new Vector3(90,0,0),Space.Self);
}
}
// Update is called once per frame
void Update () {
if ( Input.GetMouseButton(0) )
{
miniMapMove();
}
}
void OnGUI() {
switch(mmPosition)
{
case miniMapPosition.右上角:
GUI.BeginGroup(new Rect(Screen.width-miniMapW,0,miniMapW,miniMapH));
break;
case miniMapPosition.左下角:
GUI.BeginGroup(new Rect(0,Screen.height-miniMapH,miniMapW,miniMapH));
break;
}
GUI.DrawTexture(new Rect(0,0,miniMapW,miniMapH), image, ScaleMode.ScaleToFit, false, 0);
GUI.EndGroup();
GameObject[] objs = GameObject.FindGameObjectsWithTag(targetTag);
foreach(GameObject obj in objs)
{
drawFlag(obj.transform,point,4,4);
}
drawRotateFlag(cameraMain.transform,cmTexture,10,10);

}
void drawFlag(Transform tf,Texture flag,float flagW,float flagH)
{
Vector3 screenPos = cameraMap.WorldToScreenPoint(tf.position);
float wl = tf.position.x /terrionWidth;
float hl = tf.position.z /terrionHeight;
float mpw = wl * miniMapW;
float mph = miniMapH-hl *miniMapH;
// 等比例缩放
switch(mmPosition)
{
case miniMapPosition.右上角:
GUI.BeginGroup(new Rect(Screen.width-miniMapW,0,miniMapW,miniMapH));
break;
case miniMapPosition.左下角:
GUI.BeginGroup(new Rect(0,Screen.height-miniMapH,miniMapW,miniMapH));
break;
}
GUI.DrawTexture(new Rect(mpw-flagW/2,mph-flagH/2, flagW, flagH), flag);
GUI.EndGroup();

}
void drawRotateFlag(Transform tf,Texture flag,float flagW,float flagH)
{
Vector3 screenPos = cameraMap.WorldToScreenPoint(tf.position);
float wl = tf.position.x /terrionWidth;
float hl = tf.position.z /terrionHeight;
float mpw = wl * miniMapW;
float mph = miniMapH-hl *miniMapH;
// 等比例缩放
switch(mmPosition)
{
case miniMapPosition.右上角:
GUI.BeginGroup(new Rect(Screen.width-miniMapW,0,miniMapW,miniMapH));
break;
case miniMapPosition.左下角:
GUI.BeginGroup(new Rect(0,Screen.height-miniMapH,miniMapW,miniMapH));
break;
}
GUIUtility.RotateAroundPivot(cameraMain.transform.eulerAngles.y+90,new Vector2(mpw+flagW/2,mph));
GUI.DrawTexture(new Rect(mpw-flagW/2,mph-flagH/2, flagW, flagH), flag);
GUI.EndGroup();

}
/// <summary>
/// Minis the map move.
/// 换算小地图位置点到世界坐标,设置主视角位置
/// </summary>
void miniMapMove()
{
// 小地图定位场景区域
Vector3 mp = Input.mousePosition;
Debug.Log("mp:"+mp);
switch(mmPosition)
{
case miniMapPosition.右上角:
{
float miniMapX = Screen.width-miniMapW;
float miniMapY = Screen.height-miniMapH;
if ( mp.x>miniMapX && mp.y >miniMapY  )
{
float rx = mp.x - miniMapX;
float ry = mp.y - miniMapY;
float wl = rx /miniMapW;
float hl = ry /miniMapH;
cameraMain.transform.position = new Vector3(wl*terrionWidth,cameraMain.transform.position.y,hl*terrionHeight);
}
}
break;
case miniMapPosition.左下角:
{
float miniMapX = miniMapW;
float miniMapY = miniMapH;
if ( mp.x<miniMapX && mp.y <miniMapY  )
{
float rx = mp.x ;
float ry = mp.y ;
float wl = rx /miniMapW;
float hl = ry /miniMapH;
cameraMain.transform.position = new Vector3(wl*terrionWidth,cameraMain.transform.position.y,hl*terrionHeight);
}
}
break;
}

}

}

完整的工程项目下载地址:http://download.csdn.net/detail/dulgao/7276927  有分数你懂的。

如果没分数可以给我留言,我邮件发送给你。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  unity 小地图