Unity实战 RTS3D即时战略游戏开发(八) HUD的使用 小地图显示

     大家好,我是Zander,我们接着来开发Rts3D即时战略游戏开发。这一章我们讲处理HUD的显示与隐藏,首先我们找到在第一章所提供的下载链接中找到Resources—》Content3中找到HUD.Unitypackage包,把它导入到我们的项目包中。这时我们会发现在Prefabs文件夹中多了一个HUD预设。

我们把HUD预设拖到场景中,运行后如下图:


现在拥有了带当前区域的小地图,用边框表示摄像机看到的区域,还有一个信息面板,还有显示我们选中单位Icon的地方,最后面还有一个操作面板.关于UI的制作这里就不介绍了,有兴趣的同学可以自己研究一下。

  现在我们来在小地图上显示我们的位置,现在Scripts文件夹中创建一个Hud文件夹,创建Map脚本,并编辑:

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

public class Map : MonoBehaviour {

	public RectTransform ViewPort;  //小地图的视野范围
	public Transform Corner1, Corner2;     //放置在地形两个对角上标识位置的空物体 ,以便获得地形的尺寸
	public GameObject BlipPrefab;//显示玩家位置的预设
	public static Map Current;

	private Vector2 terrainSize;  //地形的大小

	private RectTransform mapRect;  //获取当前地图的位置

	public Map()
	{
		Current = this;
	}

	// Use this for initialization
	void Start () {
		terrainSize = new Vector2 (
			Corner2.position.x - Corner1.position.x,
			Corner2.position.z - Corner1.position.z);

		mapRect = GetComponent<RectTransform> ();
	}
    /// <summary>
    /// 把世界位置转成地图位置的方法
    /// </summary>
    /// <param name="point"></param>
    /// <returns></returns>
	public Vector2 WorldPositionToMap(Vector3 point)
	{
		var pos = point - Corner1.position;    //得到当前位置相对于地形起始角的位置
		var mapPos = new Vector2 (
			point.x / terrainSize.x * mapRect.rect.width,
			point.z / terrainSize.y * mapRect.rect.height);   //缩放到能适配地图尺寸的点
		return mapPos;
	}
	
	// Update is called once per frame
	void Update () {
		ViewPort.position = WorldPositionToMap (Camera.main.transform.position);
	}
}

然后在场景中创建Corner1、Corner2,如图:


,然后再给HUD下的Map添加Map组件,如图:


接下来我们要在地图上显示玩家的位置,首先在HUD文件夹下创建一个MapBlip脚本,如下

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

public class MapBlip : MonoBehaviour {

	private GameObject blip;

	public GameObject Blip { get { return blip; } }

	// Use this for initialization
	void Start () {
		blip = GameObject.Instantiate (Map.Current.BlipPrefab);  //初始化Blip物体
		blip.transform.parent = Map.Current.transform;        //
		var color = GetComponent<Player> ().Info.AccentColor;  //获取玩家的颜色
		blip.GetComponent<Image> ().color = color;
	}
	
	// Update is called once per frame
	void Update () {
		blip.transform.position = Map.Current.WorldPositionToMap (transform.position);  //更新Blip的位置
	}

	void OnDestroy()
	{
		GameObject.Destroy (blip);  //当玩家死亡后销毁Blip
	}
}

把MapBlip脚本添加到DroneUnit预设上,运行一下Unity,就会发现小地图上就会出现玩家所在的具体位置了

接下来我们要进行单位追踪处理,首先我们找到PlayerSetupDefinition脚本,在其中我们看到有一个StartingUnits的列表,但我们仅想追踪活动的单位,所以我们需要再声明一个activeUnits列表,如下:

private List<GameObject> activeUnits = new List<GameObject> ();//不让外部修改

	public List<GameObject> ActiveUnits { get { return activeUnits; } }  //方便外部访问
现在我们需要一些办法,让玩家知道新单位被添加了,但是又不想时刻去检测单位是否属于这个玩家,所以为了追踪它,我们切换到Player脚本,

添加Start()和OnDestory()方法

using UnityEngine;
using System.Collections.Generic;

public class Player : MonoBehaviour {

	public PlayerSetupDefinition Info;

	public static PlayerSetupDefinition Default;

	void Start()
	{
		Info.ActiveUnits.Add (this.gameObject);  //添加到显示列表中
	}

	void OnDestroy()
	{
		Info.ActiveUnits.Remove (this.gameObject); //在显示列表中移除
	}
}
现在我们的每个玩家都会追踪他们在游戏中所拥有的活动单位,不过现在小地图会显示所有的游戏单位,但我们只想看到一定范围内的单位,而且时刻检测所有敌对单位是否在可见范围比较消耗性能,所有我们要使用比较少耗性能的方式,我们在HUd文件夹下创建一个VisibilityManager脚本,如下:

using UnityEngine;
using System.Collections.Generic;

public class VisibilityManager : MonoBehaviour {
	public float TimeBetweenChecks = 1; //检测间隔
	public float VisibleRange = 100;    //可见距离

	private float waited = 10000;
	
	// Update is called once per frame
	void Update () {
		waited += Time.deltaTime;
		if (waited <= TimeBetweenChecks)
			return;

		waited = 0;
		List<MapBlip> pBlips = new List<MapBlip> ();  //收集玩家的blips,以便决定是否启用它
		List<MapBlip> oBlips = new List<MapBlip> ();  //收集对手的blips,以便决定是否启用它

		foreach (var p in RtsManager.Current.Players) {
			foreach(var u in p.ActiveUnits)
			{
				var blip = u.GetComponent<MapBlip>();
				if (p == Player.Default) pBlips.Add (blip);
				else oBlips.Add(blip);
			}
		}

		foreach (var o in oBlips) {
			bool active = false;
			foreach(var p in pBlips)
			{
				var distance = Vector3.Distance(o.transform.position, p.transform.position); //获取和玩家的距离
				if (distance <= VisibleRange)
				{
					active = true;
					break;
				}
			}
			o.Blip.SetActive(active);
			foreach(var r in o.GetComponentsInChildren<Renderer>()) r.enabled = active;
		}
	}
}

返回到Unity中,把VisibilityManager脚本添加到Manager上,运行Unity,就可以发现在一定距离内可以看到地方单位,超过这个距离,地方单位就会显示不见了。

好了,这一章就写到这,欢迎大家加入QQ群:280993838  或者关注我的公众号:



 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值