Unity UI框架笔记
UI框架面对的问题
- 是每个面板用一个单例还是用一个管理器管理?
- 面板的打开关闭方式,加载还是激活?销毁还是隐藏?
- 加载的面板要挂载到画布上,画布是否过场景不销毁?如果不销毁,画布是代码加载还是直接在场景里?如果是直接在,要避免回到初始场景有2个画布;
- 面板的打开有的覆盖在原面板上,不隐藏其他面板,有的隐藏其他面板。打开、隐藏面板的代码应放在哪里?如果都放在触发面板里,如果此面板要在不同环境下打开(如设置面板)
- 有些面板的初始化需要参数,参数从外部传入,无法通过Start();
- 加载面板通过资源名还是ScriptableObject引用?如果是Resources下的资源名,资源名写在哪里?硬编码在代码里好吗?如果资源要在Resources下按文件夹放,每个面板所属的文件夹怎么记录?
面板的打开关闭方式
- 加载资源、销毁对象式。省内存,费性能,垃圾多;
- 对象激活、失活式。省性能,费内存,而且编辑器里要放所有面板,很乱;
- 第一次打开是加载资源,关闭是失活对象,以后打开是激活对象。需要在打开面板方法里根据对象是否存在分开处理。多个场景会出现的面板,切场景时需要回到未加载状态;
提供加载面板的方法,包括从Resources和AB包加载,包括全屏面板和部分面板。为此需要面板预制体的路径和资源名,需要一个方法知道当前哪些面板在显示,可以是查看一个面板类的单例是否存在,也可以用一个字典存储显示的面板。
一个面板用一个单例(而不用UI管理器)会有什么问题
假设我想让面板一开始不存在场景里,第一次是加载,关闭时失活,以后打开都只激活。加载面板需要先判断这个面板加载过没有,然后决定加载还是激活。要么用面板类的静态方法(不能用实例方法因为单例还不存在),要么用一个管理器。如果用静态方法加载,这个方法不能重写,为了避免每个面板写一遍,只能写在面板基类里。
public class MyUIManager : MySingleton<MyUIManager>
{Dictionary<string,PanelBase>panelDic= new Dictionary<string,PanelBase>();Canvas _canvas;public Canvas canvas{get{if (_canvas){return _canvas;}_canvas= Object.FindFirstObjectByType<Canvas>();return _canvas;}}public void Show<T>(string folder="UI/")where T:PanelBase//通过资源名加载资源{string panelName=typeof(T).Name;if (!panelDic.ContainsKey(panelName)){GameObject panelObj = MyResManager.Instance.LoadPanel(folder+panelName);PanelBase panel = panelObj.GetComponent<PanelBase>();panelDic.Add(panelName, panel);}else{panelDic[panelName].gameObject.SetActive(true);}}public void Hide<T>(bool destroy = false)where T:PanelBase{string panelName= typeof(T).Name;if (!panelDic.ContainsKey(panelName))return;if (destroy){Object.Destroy(panelDic[panelName].gameObject);panelDic.Remove(panelName);}else{panelDic[panelName].gameObject.SetActive(false);}}public void RemovePanel(string panelName){if (panelDic.ContainsKey(panelName)){Object.Destroy(panelDic[panelName].gameObject);panelDic.Remove(panelName);}}public T GetPanel<T>()where T : PanelBase{string panelName=typeof (T).Name;if (panelDic.ContainsKey(panelName)){return (T)panelDic[panelName];}return null;}
}