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

发表于2017-06-03
评论0 1.6k浏览

这是RTS3D即时战略游戏开发系列的第七篇文章,从这开始要介绍的是处理HUD的显示与隐藏这方面的新内容,本篇是其中关于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 ();  
    }  
    ///   
    /// 把世界位置转成地图位置的方法  
    ///   
    ///   
    ///   
    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 ().Info.AccentColor;  //获取玩家的颜色  
        blip.GetComponent ().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 activeUnits = new List ();//不让外部修改  
    public List 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 pBlips = new List ();  //收集玩家的blips,以便决定是否启用它  
        List oBlips = new List ();  //收集对手的blips,以便决定是否启用它  
        foreach (var p in RtsManager.Current.Players) {  
            foreach(var u in p.ActiveUnits)  
            {  
                var blip = u.GetComponent();  
                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()) r.enabled = active;  
        }  
    }  
}  

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

Unity实战RTS3D即时战略游戏开发系列:

Unity实战 RTS3D即时战略游戏开发(一):场景

Unity实战 RTS3D即时战略游戏开发(二):玩家状态显示

Unity实战 RTS3D即时战略游戏开发(三):单位选中处理

Unity实战 RTS3D即时战略游戏开发(四):鼠标管理器

Unity实战 RTS3D即时战略游戏开发(五):NavigationMesh自动寻路

Unity实战 RTS3D即时战略游戏开发(六):信息显示

Unity实战 RTS3D即时战略游戏开发(八):HUD的使用单位信息显示

Unity实战 RTS3D即时战略游戏开发(九):行为管理器Action的使用

Unity实战 RTS3D即时战略游戏开发(十):可建造地点标示

Unity实战 RTS3D即时战略游戏开发(十一)AiController

Unity实战 RTS3D即时战略游戏开发(十二):建造AI、生产AI

Unity实战 RTS3D即时战略游戏开发(十三):战斗AI的控制

Unity实战 RTS3D即时战略游戏开发(十四)伤害更新信息显示、销毁单位、爆炸效果

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论