4.UI管理器

4.UI管理器


4.1 知识点

UI管理器类图

创建UIManager脚本。做成单例模式,确保只有一个实例存在,并且包含了存储正在显示面板的<string, BasePanel>字典和Canvas对象。在构造函数中,通过查找场景中名为”Canvas”的物体来获取Canvas对象,并使用DontDestroyOnLoad函数使其不在场景切换时被移除。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIManager
{
    private static UIManager instance = new UIManager();
    public static UIManager Instance => instance;

    // 存储面板的容器
    private Dictionary<string, BasePanel> panelDic = new Dictionary<string, BasePanel>();
    // 应该一开始就得到我们的Canvas对象 
    private Transform canvasTrans;

    private UIManager()
    {
        // 得到场景上创建好的Canvas对象
        canvasTrans = GameObject.Find("Canvas").transform;
        // 让Canvas对象过场景不移除
        // 我们通过动态创建和动态删除来显示隐藏面板,所以不删除它影响不大
        GameObject.DontDestroyOnLoad(canvasTrans.gameObject);
    }
}

注意为了让过场景的时候UI摄像机和EventSystem也不被删,可以直接把他们两作为Canvas的子对象

定义显示面板ShowPanel方法

显示面板方法首先根据泛型类型获取面板名字,然后判断是否已经有相同名字的面板被显示,如果有,则直接返回已存在的面板。如果没有,则动态创建面板的预设体,并将其设置为Canvas对象的子对象。接着获取面板脚本的实例并存储到字典中,最后调用面板的显示面板方法。

// 显示面板
public T ShowPanel<T>() where T : BasePanel
{
    // 我们只需要保证泛型T的类型和面板明一致,定义一个这样的规则就非常方便我们的使用
    string panelName = typeof(T).Name;

    // 是否已经有显示着的该面板了,如果有,不用创建,直接返回给外部使用
    if (panelDic.ContainsKey(panelName))
        return panelDic[panelName] as T;

    // 显示面板就是动态创建面板预设体并设置父对象
    // 根据得到的类名就是我们的预设体面板名,直接动态创建它即可
    GameObject panelObj = GameObject.Instantiate(Resources.Load<GameObject>("UI/" + panelName));
    panelObj.transform.SetParent(canvasTrans, false);

    // 接着就是得到对应的面板脚本存储起来
    T panel = panelObj.GetComponent<T>();
    // 把面板脚本存储到对应的容器中,之后可以方便我们获取它
    panelDic.Add(panelName, panel);
    // 调用显示自己的逻辑
    panel.ShowMe();

    return panel;
}

定义隐藏面板HidePanel方法

隐藏面板方法根据泛型类型获取面板名字,然后判断该名字的面板是否正在显示字典中。如果正在显示,则根据淡出参数决定是否淡出面板。如果淡出面板调用对应面板的隐藏方法,淡出成功后委托中传入删除面板并从字典中移除的逻辑。如果不需要淡出,直接删除面板并从字典中移除。

// 隐藏面板
// 参数一:如果希望淡出就默认传true,如果希望直接隐藏(删除)面板那么就传false
public void HidePanel<T>(bool isFade = true) where T : BasePanel
{
    // 根据泛型类型得到面板名字
    string panelName = typeof(T).Name;
    // 判断当前显示的面板有没有该名字的面板
    if (panelDic.ContainsKey(panelName))
    {
        if (isFade)
        {
            panelDic[panelName].HideMe(() =>
            {
                // 面板淡出成功后希望删除面板
                GameObject.Destroy(panelDic[panelName].gameObject);
                // 删除面板后从字典中移除
                panelDic.Remove(panelName);
            });
        }
        else
        {
            // 删除面板
            GameObject.Destroy(panelDic[panelName].gameObject);
            // 删除面板后从字典中移除
            panelDic.Remove(panelName);
        }
    }
}

定义获取面板实例GetPanel方法

获取面板实例方法根据泛型类型获取面板名字,并判断该名字的面板是否存在于字典中。如果存在,则将其转换为对应的泛型类型并返回。如果不存在,则返回null。

// 获得面板
public T GetPanel<T>() where T : BasePanel
{
    string panelName = typeof(T).Name;
    if (panelDic.ContainsKey(panelName))
        return panelDic[panelName] as T;

    // 如果没有,直接返回空
    return null;
}

4.2 知识点代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIManager
{
    private static UIManager instance = new UIManager();
    public static UIManager Instance => instance;

    //存储面板的容器
    private Dictionary<string, BasePanel> panelDic = new Dictionary<string, BasePanel>();
    //应该一开始 就得到我们的 Canvas对象 
    private Transform canvasTrans;

    private UIManager()
    {
        //得到场景上创建好的 Canvas对象
        canvasTrans = GameObject.Find("Canvas").transform;
        //让 Canvas对象 过场景 不移除 
        //我们都是通过 动态创建 和 动态删除 来显示 隐藏面板的 所以不删除它 影响不大
        GameObject.DontDestroyOnLoad(canvasTrans.gameObject);
    }

    //显示面板
    public T ShowPanel<T>() where T:BasePanel
    {
        //我们只需要保证 泛型T的类型 和 面板明 一致  定一个这样的规则 就非常方便我们的使用
        string panelName = typeof(T).Name;

        //是否已经有显示着的该面板了 如果有 不用创建 直接返回给外部使用
        if (panelDic.ContainsKey(panelName))
            return panelDic[panelName] as T;

        //显示面板 就是 动态的创建面板预设体 设置父对象
        //根据得到的 类名 就是我们的预设体面板明 直接 动态创建它 即可
        GameObject panelObj = GameObject.Instantiate(Resources.Load<GameObject>("UI/" + panelName));
        panelObj.transform.SetParent(canvasTrans, false);

        //接着 就是得到对应的面板脚本 存储起来
        T panel = panelObj.GetComponent<T>();
        //把面板脚本存储到 对应容器中 之后 可以方便我们获取它
        panelDic.Add(panelName, panel);
        //调用显示自己的逻辑
        panel.ShowMe();

        return panel;
    }

    //隐藏面板
    //参数一:如果希望 淡出 就默认传true 如果希望直接隐藏(删除)面板 那么就传false
    public void HidePanel<T>( bool isFade = true ) where T:BasePanel
    {
        //根据 泛型类型 得到面板 名字
        string panelName = typeof(T).Name;
        //判断当前显示的面板 有没有该名字的面板
        if( panelDic.ContainsKey(panelName) )
        {
            if( isFade )
            {
                panelDic[panelName].HideMe(() =>
                {
                    //面板 淡出成功后 希望删除面板
                    GameObject.Destroy(panelDic[panelName].gameObject);
                    //删除面板后 从 字典中移除
                    panelDic.Remove(panelName);
                });
            }
            else
            {
                //删除面板
                GameObject.Destroy(panelDic[panelName].gameObject);
                //删除面板后 从 字典中移除
                panelDic.Remove(panelName);
            }
        }
    }

    //获得面板
    public T GetPanel<T>() where T:BasePanel
    {
        string panelName = typeof(T).Name;
        if(panelDic.ContainsKey(panelName))
            return panelDic[panelName] as T;

        //如果没有 直接返回空
        return null;
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏