UI管理模块——UI基类
帮助面板通过代码快速找到各类子控件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
/// <summary>
/// 面板基类
/// 找到所有自己面板下的控件对象
/// 他应该提供显示或隐藏的行为
/// </summary>
public class BasePanel : MonoBehaviour
{
// 通过里氏转换原则, 来存储所有的控件
private Dictionary<string, List<UIBehaviour>> controlDic = new Dictionary<string, List<UIBehaviour>>();
void Awake()
{
FindChildrenControl<Button>();
FindChildrenControl<Image>();
FindChildrenControl<Text>();
FindChildrenControl<Toggle>();
FindChildrenControl<Slider>();
FindChildrenControl<ScrollRect>();
}
/// <summary>
/// 显示自己
/// </summary>
public virtual void ShowMe(){}
/// <summary>
/// 隐藏自己
/// </summary>
public virtual void HideMe(){}
/// <summary>
/// 找到子对象的对应控件
/// </summary>
/// <typeparam name="T"></typeparam>
private void FindChildrenControl<T>() where T : UIBehaviour
{
T[] controls = this.GetComponentsInChildren<T>();
string objName;
for (int i = 0; i < controls.Length; i++)
{
objName = controls[i].gameObject.name;
if (controlDic.ContainsKey(objName))
{
controlDic[objName].Add(controls[i]);
}
else
{
controlDic.Add(objName, new List<UIBehaviour>() { controls[i] });
}
}
}
/// <summary>
/// 得到对应名字的脚本
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="controlName"></param>
/// <returns></returns>
protected T GetControl<T>(string controlName) where T : UIBehaviour
{
if (controlDic.ContainsKey(controlName))
{
for (int i = 0; i < controlDic[controlName].Count; ++i)
{
if (controlDic[controlName][i] is T)
{
return controlDic[controlName][i] as T;
}
}
}
return null;
}
}
UI管理模块——UI管理器
管理所有显示的面板,提供给其他游戏系统接口,用来显示面板和隐藏面板
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// UI层级枚举
/// </summary>
public enum E_UI_Layer
{
Bot,
Mid,
Top,
System
}
public class UIManager : BaseManager<UIManager>
{
public Dictionary<string, BasePanel> panelDic = new Dictionary<string, BasePanel>();
//private Transform canvas;
// 为UI分层
private Transform bot; // 底层
private Transform mid; // 中层
private Transform top; // 顶层
private Transform system; // 系统层
// 记录UI的Canvas父对象 方便以后外部可能会使用他
public RectTransform canvas;
public UIManager()
{
// 创建Canvas, 让其过场景不移除
GameObject obj = ResMgr.GetInstance().Load<GameObject>("UI/Canvas");
canvas = obj.transform as RectTransform;
GameObject.DontDestroyOnLoad(obj);
// 找到各层
bot = canvas.Find("Bot");
mid = canvas.Find("Mid");
top = canvas.Find("Top");
system = canvas.Find("System");
// 创建EventSystem
obj = ResMgr.GetInstance().Load<GameObject>("UI/EventSystem");
GameObject.DontDestroyOnLoad(obj);
}
/// <summary>
/// 显示面板
/// </summary>
/// <typeparam name="T">面板脚本类型</typeparam>
/// <param name="panelName">面板名</param>
/// <param name="layer">显示在哪一层</param>
/// <param name="callBack">当面板预设体创建成功后, 想要做的事</param>
public void ShowPanel<T>(string panelName, E_UI_Layer layer = E_UI_Layer.Mid, UnityAction<T> callBack = null) where T : BasePanel
{
// 面板已经存在
if (panelDic.ContainsKey(panelName))
{
panelDic[panelName].ShowMe();
if (callBack != null)
{
callBack(panelDic[panelName] as T);
}
//// 避免面板重复加载, 如果存在该面板则直接显示, 调用回调函数后, 直接Return, 不再处理后面的异步加载
return;
}
// 异步加载面板
ResMgr.GetInstance().LoadAsync<GameObject>("UI/" + panelName, (obj) =>
{
// 把他作为Canvas的子对象, 并且要设置他的相对位置
// 找到父对象 , 显示在哪一层
Transform father = bot;
switch (layer)
{
case E_UI_Layer.Mid:
father = mid;
break;
case E_UI_Layer.Top:
father = top;
break;
case E_UI_Layer.System:
father = system;
break;
}
// 设置父对象, 相对位置和大小
obj.transform.SetParent(father,false);
obj.transform.localPosition = Vector3.zero;
obj.transform.localScale = Vector3.one;
(obj.transform as RectTransform).offsetMax = Vector2.zero;
(obj.transform as RectTransform).offsetMin = Vector2.zero;
// 得到预设体上的的面板脚本
T panel = obj.GetComponent<T>();
// 处理面板创建完成后的逻辑 (因为是异步加载面板, 要做延时处理, 只有当面板真正加载完时, 才会做外面想要做的事情.)
if (callBack != null)
{
callBack(panel);
}
panelDic[panelName].ShowMe();
// 把面板存起来
panelDic.Add(panelName, panel);
});
}
/// <summary>
/// 隐藏面板
/// </summary>
/// <param name="panelName">面板名</param>
public void HidePanel(string panelName)
{
if (panelDic.ContainsKey(panelName))
{
panelDic[panelName].HideMe();
GameObject.Destroy(panelDic[panelName].gameObject);
panelDic.Remove(panelName);
}
}
/// <summary>
/// 得到某一个已经显示的面板
/// </summary>
/// <param name="panelName">面板名</param>
public T GetPanel<T>(string panelName)where T:BasePanel
{
if(panelDic.ContainsKey(panelName))
{
return panelDic[panelName] as T;
}
return null;
}
}
使用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UITest : MonoBehaviour
{
void Start()
{
UIManager.GetInstance().ShowPanel<LoginPanel>("LoginPanel", E_UI_Layer.Bot, showPanelOver);
}
private void showPanelOver(LoginPanel panel)
{
panel.IninInfo();
Invoke("DelayHide", 1);
}
private void DelayHide()
{
UIManager.GetInstance().HidePanel("LoginPanel");
}
}
UI管理模块——优化面板基类事件监听
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
/// <summary>
/// 面板基类
/// 帮助我门通过代码快速的找到所有的子控件
/// 方便我们在子类中处理逻辑
/// 节约找控件的工作量
/// </summary>
public class BasePanel : MonoBehaviour
{
//通过里式转换原则 来存储所有的控件
private Dictionary<string, List<UIBehaviour>> controlDic = new Dictionary<string, List<UIBehaviour>>();
// Use this for initialization
protected virtual void Awake () {
FindChildrenControl<Button>();
FindChildrenControl<Image>();
FindChildrenControl<Text>();
FindChildrenControl<Toggle>();
FindChildrenControl<Slider>();
FindChildrenControl<ScrollRect>();
FindChildrenControl<InputField>();
}
/// <summary>
/// 显示自己
/// </summary>
public virtual void ShowMe()
{
}
/// <summary>
/// 隐藏自己
/// </summary>
public virtual void HideMe()
{
}
protected virtual void OnClick(string btnName)
{
}
protected virtual void OnValueChanged(string toggleName, bool value)
{
}
/// <summary>
/// 得到对应名字的对应控件脚本
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="controlName"></param>
/// <returns></returns>
protected T GetControl<T>(string controlName) where T : UIBehaviour
{
if(controlDic.ContainsKey(controlName))
{
for( int i = 0; i <controlDic[controlName].Count; ++i )
{
if (controlDic[controlName][i] is T)
return controlDic[controlName][i] as T;
}
}
return null;
}
/// <summary>
/// 找到子对象的对应控件
/// </summary>
/// <typeparam name="T"></typeparam>
private void FindChildrenControl<T>() where T:UIBehaviour
{
T[] controls = this.GetComponentsInChildren<T>();
for (int i = 0; i < controls.Length; ++i)
{
string objName = controls[i].gameObject.name;
if (controlDic.ContainsKey(objName))
controlDic[objName].Add(controls[i]);
else
controlDic.Add(objName, new List<UIBehaviour>() { controls[i] });
//如果是按钮控件
if(controls[i] is Button)
{
(controls[i] as Button).onClick.AddListener(()=>
{
OnClick(objName);
});
}
//如果是单选框或者多选框
else if(controls[i] is Toggle)
{
(controls[i] as Toggle).onValueChanged.AddListener((value) =>
{
OnValueChanged(objName, value);
});
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// UI层级
/// </summary>
public enum E_UI_Layer
{
Bot,
Mid,
Top,
System,
}
/// <summary>
/// UI管理器
/// 1.管理所有显示的面板
/// 2.提供给外部 显示和隐藏等等接口
/// </summary>
public class UIManager : BaseManager<UIManager>
{
public Dictionary<string, BasePanel> panelDic = new Dictionary<string, BasePanel>();
private Transform bot;
private Transform mid;
private Transform top;
private Transform system;
//记录我们UI的Canvas父对象 方便以后外部可能会使用它
public RectTransform canvas;
public UIManager()
{
//创建Canvas 让其过场景的时候 不被移除
GameObject obj = ResMgr.GetInstance().Load<GameObject>("UI/Canvas");
canvas = obj.transform as RectTransform;
GameObject.DontDestroyOnLoad(obj);
//找到各层
bot = canvas.Find("Bot");
mid = canvas.Find("Mid");
top = canvas.Find("Top");
system = canvas.Find("System");
//创建EventSystem 让其过场景的时候 不被移除
obj = ResMgr.GetInstance().Load<GameObject>("UI/EventSystem");
GameObject.DontDestroyOnLoad(obj);
}
/// <summary>
/// 通过层级枚举 得到对应层级的父对象
/// </summary>
/// <param name="layer"></param>
/// <returns></returns>
public Transform GetLayerFather(E_UI_Layer layer)
{
switch(layer)
{
case E_UI_Layer.Bot:
return this.bot;
case E_UI_Layer.Mid:
return this.mid;
case E_UI_Layer.Top:
return this.top;
case E_UI_Layer.System:
return this.system;
}
return null;
}
/// <summary>
/// 显示面板
/// </summary>
/// <typeparam name="T">面板脚本类型</typeparam>
/// <param name="panelName">面板名</param>
/// <param name="layer">显示在哪一层</param>
/// <param name="callBack">当面板预设体创建成功后 你想做的事</param>
public void ShowPanel<T>(string panelName, E_UI_Layer layer = E_UI_Layer.Mid, UnityAction<T> callBack = null) where T:BasePanel
{
if (panelDic.ContainsKey(panelName))
{
panelDic[panelName].ShowMe();
// 处理面板创建完成后的逻辑
if (callBack != null)
callBack(panelDic[panelName] as T);
//避免面板重复加载 如果存在该面板 即直接显示 调用回调函数后 直接return 不再处理后面的异步加载逻辑
return;
}
ResMgr.GetInstance().LoadAsync<GameObject>("UI/" + panelName, (obj) =>
{
//把他作为 Canvas的子对象
//并且 要设置它的相对位置
//找到父对象 你到底显示在哪一层
Transform father = bot;
switch(layer)
{
case E_UI_Layer.Mid:
father = mid;
break;
case E_UI_Layer.Top:
father = top;
break;
case E_UI_Layer.System:
father = system;
break;
}
//设置父对象 设置相对位置和大小
obj.transform.SetParent(father);
obj.transform.localPosition = Vector3.zero;
obj.transform.localScale = Vector3.one;
(obj.transform as RectTransform).offsetMax = Vector2.zero;
(obj.transform as RectTransform).offsetMin = Vector2.zero;
//得到预设体身上的面板脚本
T panel = obj.GetComponent<T>();
// 处理面板创建完成后的逻辑
if (callBack != null)
callBack(panel);
panel.ShowMe();
//把面板存起来
panelDic.Add(panelName, panel);
});
}
/// <summary>
/// 隐藏面板
/// </summary>
/// <param name="panelName"></param>
public void HidePanel(string panelName)
{
if(panelDic.ContainsKey(panelName))
{
panelDic[panelName].HideMe();
GameObject.Destroy(panelDic[panelName].gameObject);
panelDic.Remove(panelName);
}
}
/// <summary>
/// 得到某一个已经显示的面板 方便外部使用
/// </summary>
public T GetPanel<T>(string name) where T:BasePanel
{
if (panelDic.ContainsKey(name))
return panelDic[name] as T;
return null;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class LoginPanel : BasePanel {
//public Button btnStart;
//public Button btnQuit;
protected override void Awake()
{
//一定不能少 因为需要执行父类的awake来初始化一些信息 比如找控件 加事件监听
base.Awake();
//在下面处理自己的一些初始化逻辑
}
// Use this for initialization
void Start () {
//GetControl<Button>("btnStart").onClick.AddListener(ClickStart);
//GetControl<Button>("btnQuit").onClick.AddListener(ClickQuit);
UIManager.AddCustomEventListener(GetControl<Button>("btnStart"), EventTriggerType.PointerEnter, (data)=>{
Debug.Log("进入");
});
UIManager.AddCustomEventListener(GetControl<Button>("btnStart"), EventTriggerType.PointerExit, (data) => {
Debug.Log("离开");
});
}
private void Drag(BaseEventData data)
{
}
private void PointerDown(BaseEventData data)
{
}
// Update is called once per frame
void Update () {
}
public override void ShowMe()
{
base.ShowMe();
//显示面板时 想要执行的逻辑 这个函数 在UI管理器中 会自动帮我们调用
//只要重写了它 就会执行里面的逻辑
}
protected override void OnClick(string btnName)
{
switch(btnName)
{
case "btnStart":
Debug.Log("btnStart被点击");
break;
case "btnQuit":
Debug.Log("btnQuit被点击");
break;
}
}
protected override void OnValueChanged(string toggleName, bool value)
{
//在这来根据名字判断 到底是那一个单选框或者多选框状态变化了 当前状态就是传入的value
}
public void InitInfo()
{
Debug.Log("初始化数据");
}
//点击开始按钮的处理
public void ClickStart()
{
}
//点击开始按钮的处理
public void ClickQuit()
{
Debug.Log("S");
}
}
UI管理模块——自定义事件监听
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
/// <summary>
/// UI层级
/// </summary>
public enum E_UI_Layer
{
Bot,
Mid,
Top,
System,
}
/// <summary>
/// UI管理器
/// 1.管理所有显示的面板
/// 2.提供给外部 显示和隐藏等等接口
/// </summary>
public class UIManager : BaseManager<UIManager>
{
public Dictionary<string, BasePanel> panelDic = new Dictionary<string, BasePanel>();
private Transform bot;
private Transform mid;
private Transform top;
private Transform system;
//记录我们UI的Canvas父对象 方便以后外部可能会使用它
public RectTransform canvas;
public UIManager()
{
//创建Canvas 让其过场景的时候 不被移除
GameObject obj = ResMgr.GetInstance().Load<GameObject>("UI/Canvas");
canvas = obj.transform as RectTransform;
GameObject.DontDestroyOnLoad(obj);
//找到各层
bot = canvas.Find("Bot");
mid = canvas.Find("Mid");
top = canvas.Find("Top");
system = canvas.Find("System");
//创建EventSystem 让其过场景的时候 不被移除
obj = ResMgr.GetInstance().Load<GameObject>("UI/EventSystem");
GameObject.DontDestroyOnLoad(obj);
}
/// <summary>
/// 通过层级枚举 得到对应层级的父对象
/// </summary>
/// <param name="layer"></param>
/// <returns></returns>
public Transform GetLayerFather(E_UI_Layer layer)
{
switch (layer)
{
case E_UI_Layer.Bot:
return this.bot;
case E_UI_Layer.Mid:
return this.mid;
case E_UI_Layer.Top:
return this.top;
case E_UI_Layer.System:
return this.system;
}
return null;
}
/// <summary>
/// 显示面板
/// </summary>
/// <typeparam name="T">面板脚本类型</typeparam>
/// <param name="panelName">面板名</param>
/// <param name="layer">显示在哪一层</param>
/// <param name="callBack">当面板预设体创建成功后 你想做的事</param>
public void ShowPanel<T>(string panelName, E_UI_Layer layer = E_UI_Layer.Mid, UnityAction<T> callBack = null) where T : BasePanel
{
if (panelDic.ContainsKey(panelName))
{
panelDic[panelName].ShowMe();
// 处理面板创建完成后的逻辑
if (callBack != null)
callBack(panelDic[panelName] as T);
//避免面板重复加载 如果存在该面板 即直接显示 调用回调函数后 直接return 不再处理后面的异步加载逻辑
return;
}
ResMgr.GetInstance().LoadAsync<GameObject>("UI/" + panelName, (obj) =>
{
//把他作为 Canvas的子对象
//并且 要设置它的相对位置
//找到父对象 你到底显示在哪一层
Transform father = bot;
switch (layer)
{
case E_UI_Layer.Mid:
father = mid;
break;
case E_UI_Layer.Top:
father = top;
break;
case E_UI_Layer.System:
father = system;
break;
}
//设置父对象 设置相对位置和大小
obj.transform.SetParent(father);
obj.transform.localPosition = Vector3.zero;
obj.transform.localScale = Vector3.one;
(obj.transform as RectTransform).offsetMax = Vector2.zero;
(obj.transform as RectTransform).offsetMin = Vector2.zero;
//得到预设体身上的面板脚本
T panel = obj.GetComponent<T>();
// 处理面板创建完成后的逻辑
if (callBack != null)
callBack(panel);
panel.ShowMe();
//把面板存起来
panelDic.Add(panelName, panel);
});
}
/// <summary>
/// 隐藏面板
/// </summary>
/// <param name="panelName"></param>
public void HidePanel(string panelName)
{
if (panelDic.ContainsKey(panelName))
{
panelDic[panelName].HideMe();
GameObject.Destroy(panelDic[panelName].gameObject);
panelDic.Remove(panelName);
}
}
/// <summary>
/// 得到某一个已经显示的面板 方便外部使用
/// </summary>
public T GetPanel<T>(string name) where T : BasePanel
{
if (panelDic.ContainsKey(name))
return panelDic[name] as T;
return null;
}
/// <summary>
/// 给控件添加自定义事件监听
/// </summary>
/// <param name="control">控件对象</param>
/// <param name="type">事件类型</param>
/// <param name="callBack">事件的响应函数</param>
public static void AddCustomEventListener(UIBehaviour control, EventTriggerType type, UnityAction<BaseEventData> callBack)
{
EventTrigger trigger = control.GetComponent<EventTrigger>();
if (trigger == null)
trigger = control.gameObject.AddComponent<EventTrigger>();
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = type;
entry.callback.AddListener(callBack);
trigger.triggers.Add(entry);
}
}
下一篇:12 - 音效管理模块