Unity UI层级管理框架

发表于2017-12-28
评论0 5k浏览

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

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论