使用建造者模式来构建整个结构,由UIManager统一管理UIBase、UIWidget和UISubBase,UIManager本身使用的是单例模式。
UIManager
UIManager提供注册和注销方法,供UIBase、UIWidget和UISubBase组册使用。
外界调用UIBase、UIWidget和UISubBase只能通过UIManager。
UI的显示和切换功能也是在这里执行的。
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class UIManager : MonoBehaviour
{
public static UIManager instance;
/// <summary>
/// 主画布
/// </summary>
public Transform mainCanvas;
private void Awake()
{
instance = this;
uiWidgets = new Dictionary<string, Dictionary<string, UIWidget>>();
mainCanvas = GameObject.FindGameObjectWithTag("MainCanvas").transform;
if (uiBases == null)
{
// 初始化
uiBases = new Dictionary<string, UIBase>();
}
}
private void Update()
{
if (currentUIPanelOnStay != null)
{
currentUIPanelOnStay();
}
}
/// <summary>
/// 存储所有需要操作的部件
/// </summary>
private Dictionary<string, Dictionary<string, UIWidget>> uiWidgets;
/// <summary>
/// 获得Widget
/// </summary>
/// <param name="panelName"></param>
/// <param name="widgetName"></param>
/// <returns></returns>
public UIWidget ObtainUIWidget(string panelName, string widgetName)
{
if (uiWidgets.ContainsKey(panelName))
{
return uiWidgets[panelName][widgetName];
}
return null;
}
/// <summary>
/// 获取 UISubWidget
/// </summary>
/// <param name="panelName"></param>
/// <param name="widgetName"></param>
/// <param name="uiSubBaseName"></param>
/// <param name="uiSubWidgetName"></param>
/// <returns></returns>
public UISubWidget ObtainUISubWidget(string panelName, string widgetName, string uiSubBaseName,
string uiSubWidgetName)
{
UIWidget uiWidget = ObtainUIWidget(panelName, widgetName);
if (uiWidget == null)
{
return null;
}
return uiWidget.ObtainUISubWidget(uiSubBaseName, uiSubWidgetName);
}
/// <summary>
/// 注册Widget
/// </summary>
/// <param name="panelName"></param>
/// <param name="widgetName"></param>
/// <param name="uiWidget"></param>
public void RegisterUIWidget(string panelName, string widgetName, UIWidget uiWidget)
{
if (!uiWidgets.ContainsKey(panelName))
{
uiWidgets[panelName] = new Dictionary<string, UIWidget>();
}
uiWidgets[panelName].Add(widgetName, uiWidget);
}
/// <summary>
/// 注销Widget
/// </summary>
/// <param name="panelName"></param>
/// <param name="widgetName"></param>
public void UnregisterUIWidget(string panelName, string widgetName)
{
if (uiWidgets.ContainsKey(panelName))
{
if (uiWidgets[panelName].ContainsKey(widgetName))
{
uiWidgets[panelName].Remove(widgetName);
}
}
}
/// <summary>
/// 注销Panel
/// </summary>
/// <param name="panelName"></param>
public void UnregisterUIPanel(string panelName)
{
if (uiWidgets.ContainsKey(panelName))
{
uiWidgets[panelName].Clear();
uiWidgets[panelName] = null;
uiWidgets.Remove(panelName);
}
}
/// <summary>
/// 获取主画布
/// </summary>
/// <returns></returns>
public Transform ObtainMainCanvas()
{
return mainCanvas;
}
#region UI Switch
/// <summary>
/// 当前显示的 UIPanel
/// </summary>
private string currentUIPanel;
/// <summary>
/// 当前 UIPanel 的更新方法
/// </summary>
private UnityAction currentUIPanelOnStay;
/// <summary>
/// 当前初始化的所有 UI
/// </summary>
private Dictionary<string, UIBase> uiBases;
/// <summary>
/// 切换到指定的 UIPanel
/// </summary>
/// <param name="panelName"></param>
public void SwitchToPanel(string panelName)
{
// 如果当前 UIPanel 为要打开的 UIPanel
if (currentUIPanel == panelName)
{
return;
}
// 如果 UIPanel 没有创建
if (!uiBases.ContainsKey(panelName))
{
CreateUIPanel(panelName);
}
// 切换显示的 UIPanel
if (currentUIPanel != null)
{
HideUIPanel(currentUIPanel);
}
DisplayUIPanel(panelName);
}
/// <summary>
/// 创建新的 UIPanel
/// </summary>
/// <param name="prefabName"></param>
private void CreateUIPanel(string prefabName)
{
GameObject prefab = ResourceAndDataManager.Instance.ObtainPrefab(prefabName);
// 生成对象
GameObject gameObject = Instantiate(prefab);
// 取出掉 "(Clone)"
gameObject.name = StringTool.CullClone(gameObject.name);
// 设置 Rotation
gameObject.transform.rotation = Quaternion.identity;
// 设置父对象
gameObject.transform.SetParent(ObtainMainCanvas(), false);
// 添加创建的 UIPanel 到字典
uiBases.Add(prefabName, gameObject.GetComponent<UIBase>());
}
/// <summary>
/// 显示 UIPanel
/// </summary>
/// <param name="panelName"></param>
private void DisplayUIPanel(string panelName)
{
// 设置当前显示的 UIPanel
currentUIPanel = panelName;
uiBases[currentUIPanel].OnEnter();
// 设置当前 UIPanel 更新方法
currentUIPanelOnStay = uiBases[currentUIPanel].OnStay;
}
/// <summary>
/// 隐藏 UIPanel
/// </summary>
/// <param name="panelName"></param>
private void HideUIPanel(string panelName)
{
uiBases[panelName].OnExit();
}
/// <summary>
/// 获取当前显示的 UIPanel 名称
/// </summary>
/// <returns></returns>
public string ObtainCurrentUIPanelName()
{
return currentUIPanel;
}
/// <summary>
/// 获取当前显示的 UIPanel
/// </summary>
/// <returns></returns>
public UIBase ObtainCurrentUIPanel()
{
return uiBases[currentUIPanel];
}
/// <summary>
/// 通过名称获取 UIPanel
/// </summary>
/// <param name="uiPanelName"></param>
/// <returns></returns>
public UIBase ObtainUIPanelByName(string uiPanelName)
{
return uiBases[uiPanelName];
}
#endregion
}
UIBase
所有UIController的基类。
包括进入、停留、离开回调方法,提供调用UIWidget自身方法来获取和修改Panel下面组件的方法,添加Panel下面组件的各种事件。
搜索自身所有下级游戏对象,给标记了特定后缀(我这里设置的是"_N")的游戏对象添加UIWidget。
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
public class UIBase : MonoBehaviour
{
private CanvasGroup canvasGroup;
public virtual void Awake()
{
canvasGroup = GetComponent<CanvasGroup>();
// 在所有需要操作的部件上添加UIWidget脚本
Transform[] children = GetComponentsInChildren<Transform>();