Unity UI层级管理框架

来源:互联网 发布:广州市云润大数据 编辑:程序博客网 时间:2024/05/29 15:54

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 initializationvoid 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 initializationvoid 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);    }}