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