用来管理UI界面的利器-UI框架

2021-06-08 21:36发布

本节今天和大家分享一个Unity中的UI框架,一款游戏中的界面是非常多的,少则几十多则上百,如此众多的界面我们如何去控制其何时加载何时关闭,这就需要我们搭建一个UI框架来管理界面,所有的界面的创建和隐藏都是通过该UI框架完成。

首先需要创建一个UIManager脚本文件,并将其设置为单例模式,如下:

public class UIManager : MonoBehaviour
{
    public static UIManager instance;
    public static UIManager getInstance()
    {
        return instance;
}
void Awake()
    {
        instance = this;
}
}

接下来添加两个画布游戏对象,UICanvasObj画布为普通画布,一般界面都放在该画布下,TopCanvasObj画布的order会高于UICanvasObj,一般会将加载界面放在该画布下,这样就可以保证无论何时加载界面都始终在所有界面的最上面显示。

public static GameObject UICanvasObj;

public static GameObject TopCanvasObj;

 

Awake方法中添加如下代码:

UICanvasObj = GameObject.Find("Canvas");

TopCanvasObj = GameObject.Find("TopCanvas");

画布order设置如下图:

接下来定义一个字典用来存储当前已加载界面对象,这样当第一次创建界面时添加到字典中,后续控制界面显示与隐藏直接通过字典获取即可,避免每次都重复创建界面,消耗资源,代码如下:

private Dictionary<PanelEnum, Transform> UIModules;

Awake中添加以下代码:

UIModules = new Dictionary<PanelEnum, Transform>();

由于切换界面过程中不能销毁当前管理类所以还需添加以下代码在Awake中:

DontDestroyOnLoad(TopCanvasObj);

DontDestroyOnLoad(gameObject);

接下来就可以添加LoadAndShowPanelByName方法来创建界面了,该方法主要从Resource文件夹中加载界面并添加到字典中,如果已经在字典中存在那么直接获取并返回,代码如下:

/// <summary>
    /// 根据界面名称加载并显示UI界面
    /// </summary>
    /// <param name="panelName"></param>
    public void LoadAndShowPanelByName(PanelEnum panelName, PanelCanvas panelCanvas)
    {
        if (UIModules.ContainsKey(panelName))
        {
            Transform panel = null;
            UIModules.TryGetValue(panelName, out panel);
 
            if (panel == null)
            {
                //如果字典中key值对应的value值已销毁那么将键值对移除,重新创建该界面
                UIModules.Remove(panelName);
            }
            else
            {
                panel.gameObject.SetActive(true);
                return;
            }
        }
 
        GameObject parentCanvas = null;
 
        switch (panelCanvas)
        {
            case PanelCanvas.UICanvasObj:
                if (UICanvasObj == null)
                {
                    UICanvasObj = GameObject.Find("Canvas");
                }
                parentCanvas = UICanvasObj;
                break;
            case PanelCanvas.TopCanvasObj:
                if (TopCanvasObj == null)
                {
                    TopCanvasObj = GameObject.Find("TopCanvas");
                }
                parentCanvas = TopCanvasObj;
                break;
        }
 
        string panelResource = uiPath + "/" + panelName.ToString();
        GameObject panelGO = Resources.Load(panelResource) as GameObject;
        panelGO = Instantiate(panelGO, parentCanvas.transform);//实例化预制体
        panelGO.transform.localPosition = Vector3.zero;
        panelGO.gameObject.SetActive(true);
        UIModules.Add(panelName, panelGO.transform);
    }
接下来添加HidePanelByName方法来隐藏界面,代码如下:
/// <summary>
    /// 根据界面名称隐藏UI界面
    /// </summary>
    /// <param name="panelName"></param>
    public void HidePanelByName(PanelEnum panelName)
    {
        Transform panel = null;
        if (!UIModules.ContainsKey(panelName))
        {
            return;
        }
        UIModules.TryGetValue(panelName, out panel);
        panel.gameObject.SetActive(false);
    }
 
也可继续进行扩展,如果想要获取某个界面的对象可以继续添加GetPanelByName方法,调用该方法后可以返回界面对象,代码如下:
/// <summary>
    /// 根据界面名称查找指定panel对象
    /// </summary>
    /// <param name="panelName"></param>
    /// <returns></returns>
    public Transform GetPanelByName(PanelEnum panelName)
    {
        Transform panel = null;
        if (UIModules.ContainsKey(panelName))
        {
            UIModules.TryGetValue(panelName,out panel);
        }
        return panel;
    }

这样一个基础的UI管理框架就搭建完成了,后续可以继续进行扩展,今天的分享就到这里,大家有什么问题可以私聊我。