Unity UI层级管理框架
发表于2017-12-28
1.为什么要使用UI层级管理框架?
根据我个人写的UI层级总结出:在一般UI界面的 Canvas 下有多个Panel,每个Panel下又有很多个需要操作的控件(Image、Text、inputField、Button)等,
因此要去管理如此多的事件处理非常繁琐,UI的层级结构刚好适合用一套框架来管理 :Canvas--->Panel--->(控件)
例:
第一步:给需要监听鼠标事件的控件添加监听脚本
用一个脚本代替 控件在Inspector中留下的OnClick方法(例:Button的OnClick需要去在脚本中寻找相对应的方法,如果脚本多了,寻找方法困难,而且不利于扩展)
因此我用了一个 OnTriggerEvent.cs 的脚本来执行相应的点击事件
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; public class OnTriggerEvent : EventTrigger { //通过委托事件让UIScene来分配事件 public delegate void ClickListener(); public event ClickListener onBeginDrag; public event ClickListener onDrag; public event ClickListener onEndDrag; public event ClickListener onPointerClick; public event ClickListener onPointerUp; ///UI的相关监听//鼠标进入 public override void OnBeginDrag(PointerEventData eventdata) { if (onBeginDrag != null) onBeginDrag(); } public override void OnDrag(PointerEventData eventdata) { if (onDrag != null) onDrag(); } public override void OnEndDrag(PointerEventData eventdata) { if (onEndDrag != null) onEndDrag(); } public override void OnPointerClick(PointerEventData eventdata) { if (onPointerClick != null) onPointerClick(); } public override void OnPointerUp(PointerEventData eventdata) { if (onPointerUp != null) onPointerUp(); } }
第二步:给Panel添加脚本管理其下面需要监听的各个控件
using System.Collections; using System.Collections.Generic; using UnityEngine; public class UIscene : MonoBehaviour { /// <summary> /// 管理所有需要监听的子物体 /// </summary> Dictionary<string,OnTriggerEvent> items=new Dictionary<string, OnTriggerEvent>(); // Use this for initialization public void Start () { Init(); } /// <summary> /// 根据名字在字典当中获取子物体 /// </summary> public OnTriggerEvent GetTrigger(string name) { if (items.ContainsKey(name)) return items[name]; return null; } public void Init() { //调用Find方法找到这个Panel下面带有OnTriggerEvent组件的所有子物体 Find(transform); } //递归查找子物体 public void Find(Transform t) { OnTriggerEvent item = t.GetComponent<OnTriggerEvent>(); if (item != null) { string name = item.gameObject.name; if (!items.ContainsKey(name)) { items.Add(name, item); } } for (int i = 0; i < t.childCount; i++) { Find(t.GetChild(i)); } } }
第三步:给Canvas添加管理各个Panel的脚本 UIManager.cs
可以创建一个单例作为全局管理的类
如:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class UIPanel<T> : MonoBehaviour where T:Component{ private static T target; public static T Intance { get{ target = GameObject.FindObjectOfType(typeof(T)) as T; if (target == null) { GameObject go = new GameObject(); target = go.AddComponent<T>(); } return target; } } }
UIManager继承这个单例,方便使用
using System.Collections; using System.Collections.Generic; using UnityEngine; //因为有些Panel的名称复杂,所以通过静态类、字段存一些Panel的名称,方便我们索引 public class UISceneName { public const string Panel_login = "Panel_Login"; public const string Panel_ChooseAndEnter = "Panel_ChooseAndEnter"; public const string Panel_CreateCharacter = "Panel_CreateCharacter"; public const string Panel_Main = "Panel_Main"; public const string Panel_Hero="Panel_Hero"; // public const string Panel_Register="Panel_Register"; // public const string } public class UIManager : UIPanel<UIManager> { //创建一个字典来保存所有 Panel Dictionary<string,UIscene> scenes = new Dictionary<string,UIscene>(); public void Init() { UIscene[] items = GameObject.FindObjectsOfType<UIscene>(); for (int i = 0; i < items.Length; i++) { UIscene go =items[i]; if (!scenes.ContainsKey(go.name)) { scenes.Add(go.name, go); go.gameObject.SetActive(false); } } } //获取UIscene public UIscene GetUIscene(string name) { if (scenes.ContainsKey(name)) { return scenes[name]; } return null; } //对UIScene组件的Panel是否激活 public void IsActive(string name,bool isActive) { GameObject go = scenes[name].gameObject; if (go == null) { Debug.Log("你要查找的物体丢"); return; } go.gameObject.SetActive(isActive); } //展现登录界面的UIScene public void ShowUI() { IsActive(UISceneName.Panel_login, true); } }
第四步:前面三步都是管理思想,并提供了很多接口,
初始化整个UI
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Init : MonoBehaviour { // Use this for initialization void Start () { UIManager.Intance.Init(); UIManager.Intance.ShowUI(); } }
第五步:外部的使用:通过继承UIScene的到整个Panel下面的所有需要监听的控件
如:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ToMain : UIscene { private OnTriggerEvent Button_ToMain; // Use this for initialization void Start () { base.Start(); Button_ToMain = GetTrigger("Button_ToMain"); //给返回按钮绑定事件 Button_ToMain.onPointerClick += HeroToMain; } //返回到主界面 private void HeroToMain() { //关闭英雄界面 UIManager.Intance.IsActive(UISceneName.Panel_Hero, false); //打开主界面 UIManager.Intance.IsActive(UISceneName.Panel_Main, true); } }