Unity UI层级管理框架

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/leonardo_Davinci/article/details/78401907

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




猜你喜欢

转载自blog.csdn.net/leonardo_Davinci/article/details/78401907
今日推荐