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

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  有分数你懂的。

如果没分数可以给我留言,我邮件发送给你。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值