unity设计模式11_UI管理器

1.引入

前面我们用一个UI基类来对一个Panel下的所有组件进行管理,现在我们要对一个Canvas下的所有Panel进行统一管理,即显示和隐藏Panel
一般有两种办法进行显示和隐藏Panel:

1.设置Panel的Active(SetActive)为true或者false,即显示或隐藏Panel
2.将Panel做成预设体,进行实例化和销毁Panel

前者如果面板过多,会占用过多的内存,所以我们选择后者

2.思路

写一个UIManager

为了统一管理(有时需要显示的Panel不止一个),我们用一个字典来存放显示的Panel,即是:

Dictionary<string, PanelBase> dic = new Dictionary<string, PanelBase>();

注:PanelBase为前面的UI基类,即所有Panel脚本的父类

2.1显示面板的实现

2.1.1那么我们在实例化Panel时候也需要考虑层级问题,为此,我们将Canvas进行如下操作:
在这里插入图片描述
此处的Bottom、Medium、Top,System分别对应显示的不同层级。在实例化时只要放在需要显示的对应层级下(作为对应层的子物体

注:在hierarchy面板中的UI层越靠前越先渲染,即越底层,可能被遮挡。

为了方便,我们将Canvas和EventSystem也做成预设体,在UIManager的构造函数中实例化,因为是单例,所以只会被实例化一次,即Cavas和EventSystem也只会被实例化一次。

2.1.2 实例化面板后,我们通常要对面板的一些信息进行更新,所以函数的参数还可以设置一个委托在实例化后调用(因为此处是异步加载资源,所以在外部不知道什么时候加载完毕,需要专门设置一个参数调用实例化后的函数)

2.1.3 面板显示函数:

	/// <summary>
	/// 显示面板
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="name"></param>
	/// <param name="layout"></param>
	/// <param name="action"></param>
	public void ShowPanel<T>(string name,UI_Layout layout= UI_Layout.SYSTEM, UnityAction<T> action=null) where T: PanelBase
	{
		//如果字典中存在该面板,即已经在显示该面板
		if(dic!=null&&dic.ContainsKey(name))
		{
			T t = dic[name].GetComponent<T>();
			if(action!=null)
			action(t);
			return;
		}

		//确定显示的层级
		Transform father= canvas.Find("System");
		ResourcesManager.GetInstance().LoadResourceAsync<GameObject>("UI/" + name, (o) => 
		{ 
			switch(layout)
			{
				case UI_Layout.BOTTOM: father = canvas.Find("Bottom");break;
				case UI_Layout.MEDIUM: father = canvas.Find("Medium");break;
				case UI_Layout.TOP: father = canvas.Find("Top");break;
			}
			//设置显示的参数
			o.name = name;
			o.transform.SetParent(father);
			o.transform.localPosition = Vector3.zero;
			o.transform.localScale = Vector3.one;
			(o.transform as RectTransform).offsetMax = Vector2.zero;
			(o.transform as RectTransform).offsetMin = Vector2.zero;

			//执行显示后的操作
			T t = o.GetComponent<T>();
			if(action!=null)
			action(t);

			//存储到字典中[注意此处只存脚本是因为我们对panel的操作一般体现在调用panel的方法]
			dic.Add(name, t);
		});
	}

2.2隐藏面板
只需进行销毁从字典中移除的操作即可。

3.所有代码

public class UIManager : SingeCaseBase<UIManager>
{
	//面板层级
	public enum UI_Layout {
		TOP,
		BOTTOM,
		MEDIUM,
		SYSTEM,
	};

	
	Transform canvas;

	/// <summary>
	/// 创建Canvas和EventSystem
	/// </summary>
	public UIManager()
	{
		canvas = ResourcesManager.GetInstance().LoadResource<GameObject>("UI/Canvas").transform;
		GameObject.DontDestroyOnLoad(canvas);
		GameObject eventSystem = ResourcesManager.GetInstance().LoadResource<GameObject>("UI/EventSystem");
		GameObject.DontDestroyOnLoad(eventSystem);
	}

	Dictionary<string, PanelBase> dic = new Dictionary<string, PanelBase>();


	/// <summary>
	/// 显示面板
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="name"></param>
	/// <param name="layout"></param>
	/// <param name="action"></param>
	public void ShowPanel<T>(string name,UI_Layout layout= UI_Layout.SYSTEM, UnityAction<T> action=null) where T: PanelBase
	{
		//如果字典中存在该面板,即已经在显示该面板
		if(dic!=null&&dic.ContainsKey(name))
		{
			T t = dic[name].GetComponent<T>();
			if(action!=null)
			action(t);
			return;
		}

		//确定显示的层级
		Transform father= canvas.Find("System");
		ResourcesManager.GetInstance().LoadResourceAsync<GameObject>("UI/" + name, (o) => 
		{ 
			switch(layout)
			{
				case UI_Layout.BOTTOM: father = canvas.Find("Bottom");break;
				case UI_Layout.MEDIUM: father = canvas.Find("Medium");break;
				case UI_Layout.TOP: father = canvas.Find("Top");break;
			}
			//设置显示的参数
			o.name = name;
			o.transform.SetParent(father);
			o.transform.localPosition = Vector3.zero;
			o.transform.localScale = Vector3.one;
			(o.transform as RectTransform).offsetMax = Vector2.zero;
			(o.transform as RectTransform).offsetMin = Vector2.zero;

			//执行显示后的操作
			T t = o.GetComponent<T>();
			if(action!=null)
			action(t);

			//存储到字典中[注意此处只存脚本是因为我们对panel的操作一般体现在调用panel的方法]
			dic.Add(name, t);
		});
	}

	/// <summary>
	/// 隐藏面板
	/// </summary>
	/// <param name="name"></param>
	public void HidePanel(string name)
	{
		if(dic.ContainsKey(name))
		{
			//销毁并移除
			GameObject.Destroy(dic[name].gameObject);
			dic.Remove(name);
		}
	}
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值