概述
主要包含:统一控制Panel全屏界面面板及Popup弹窗的显示隐藏,通知消息弹窗,按钮自动添加点击音效
UIManager:统一管理类,统一控制各个界面的显示及隐藏
界面隐藏时,是将界面SetActive(false)了(没有写刷新函数,如果界面已显示,再次调用显示时,最好刷新一次界面),也可以直接Destroy(gameObject)销毁,下次显示时重新创建
在加载创建UI界面时,会给每个Button和Toggle自动添加点击音效(配合音效管理类使用),这里只用了一个通用音效,如果需要多个不同音效,可以给每个界面加一个标记(比如Base类添加一个枚举值,或者界面命名加一个后缀,用name.EndsWith("sign")区分),根据标记绑定对应音效
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.UI;
using System.Linq;
using DG.Tweening;
public class UIManager : MonoSingleton<UIManager>
{
public Camera uiCamera { get; private set; }
Transform panelNode;
Transform popupNode;
Transform barNode;
void Awake()
{
Init();
}
void Start()
{
uiCamera = MainManager.Instance.GetComponentInChildren<Camera>();
ShowPanel<UIStartupPanel>(true);
}
void Init()
{
panelNode = transform.Find("PanelRoot");
if (panelNode == null)
panelNode = transform;
popupNode = transform.Find("PopupRoot");
if (popupNode == null)
popupNode = transform;
barNode = transform.Find("BarNode");
if (barNode == null)
barNode = transform;
}
#region --- Panel & Popup ---
Dictionary<Type, UIBase> uiDic = new Dictionary<Type, UIBase>();
public T LoadUI<T>(params object[] args) where T : UIBase
{
Type uiType = typeof(T);
if (uiDic.ContainsKey(uiType))
{
uiDic[uiType].Destroy();
uiDic.Remove(uiType);
}
T uiPrefab = ResourcesLoader.LoadObject<T>(ConstConfig.uiPrefabPath, uiType.Name);
if (uiPrefab == null)
return null;
T ui = Instantiate(uiPrefab, transform);
if (uiPrefab is UIPanelBase)
{
ui.transform.SetParent(panelNode);
}
else if (uiPrefab is UIPopupBase)
{
ui.transform.SetParent(popupNode);
}
else if (uiPrefab is UIBarBase)
{
ui.transform.SetParent(barNode);
}
uiDic.Add(uiType, ui);
AddButtonClickSound(ui.transform);
ui.Init(args);
return ui;
}
public T GetUI<T>() where T : UIBase
{
Type uiType = typeof(T);
if (!uiDic.ContainsKey(uiType))
LoadUI<T>();
if (uiDic.ContainsKey(uiType))
return uiDic[uiType] as T;
return null;
}
public bool ShowPanel<T>(bool hideOther, params object[] args) where T : UIPanelBase
{
if (hideOther)
HideAllPanel();
//if (showTopBar)
// ShowUI<UITopBar>();
//else
// HideUI<UITopBar>();
return ShowUI<T>(args);
}
public bool ShowUI<T>(params object[] args) where T : UIBase
{
Type uiType = typeof(T);
if (!uiDic.ContainsKey(uiType))
LoadUI<T>();
if (uiDic.ContainsKey(uiType))
return ShowUI(uiDic[uiType], args);
return false;
}
public bool ShowUI(UIBase ui, params object[] args)
{
if (ui == null)
return false;
ui.Show(args);
return true;
}
public bool ShowNotify(UINotifyInfo notifyInfo)
{
return ShowUI<UINotifyPopup>(notifyInfo);
}
public bool ShowNotify(string notifyInfoStr)
{
return ShowUI<UINotifyPopup>(new UINotifyInfo() { infoStr = notifyInfoStr });
}
public bool HideUI<T>(float delayTime = 0) where T : UIBase
{
Type uiType = typeof(T);
if (uiDic.ContainsKey(uiType))
return HideUI(uiDic[uiType], delayTime);
return false;
}
public bool HideUI(UIBase ui, float delayTime)
{
if (ui == null)
return false;
if (delayTime > 0)
ui.HideDelay(delayTime);
else
ui.Hide();
return true;
}
public void HideAllPanel()
{
var panelDic = uiDic.Where(pair => pair.Value is UIPanelBase);
foreach (var item in panelDic)
{
item.Value.Hide();
}
}
public void HideAllPopup()
{
var popupDic = uiDic.Where(pair => pair.Value is UIPopupBase);
foreach (var item in popupDic)
{
item.Value.Hide();
}
}
public bool DestroyUI<T>() where T : UIBase
{
Type uiType = typeof(T);
if (uiDic.ContainsKey(uiType))
{
UIBase toDestroyUI = uiDic[uiType];
uiDic.Remove(uiType);
return DestroyUI(toDestroyUI);
}
return false;
}
public bool DestroyUI(UIBase ui)
{
if (ui == null)
return false;
if (ui.isShow)
ui.Hide();
ui.Destroy();
return true;
}
public void DestroyAllUI()
{
foreach (var item in uiDic.Values)
{
item.Destroy();
}
uiDic.Clear();
}
#endregion
#region --- AddButtonClickSound ---
public static void GetAllButtonAddListener(Action btnAction)
{
//获取场景所有物体
Button[] allButtons = Resources.FindObjectsOfTypeAll<Button>();
for (int i = 0; i < allButtons.Length; i++)
{
allButtons[i].onClick.AddListener(() => btnAction());
}
Debug.Log("<color=green>当前场景共有Button组件 : </color>" + allButtons.Length);
}
public static void AddButtonClickSound(Transform targetObj)
{
Button[] buttons = targetObj.GetComponentsInChildren<Button>();
for (int i = 0; i < buttons.Length; i++)
{
int index = i;
buttons[index].onClick.AddListener(() => {
AudioConteoller.Instance.PlaySoundOnce(ConstConfig.uiBtnClipName);
buttons[index].transform.localScale = Vector3.one;
buttons[index].transform.DOKill();
buttons[index].transform.DOShakeScale(0.3f, 0.5f);
});
}
Toggle[] toggles = targetObj.GetComponentsInChildren<Toggle>();
for (int i = 0; i < toggles.Length; i++)
{
int index = i;
toggles[index].onValueChanged.AddListener((b) =>
{
if (b)
{
AudioConteoller.Instance.PlaySoundOnce(ConstConfig.uiBtnClipName);
toggles[index].transform.localScale = Vector3.one;
toggles[index].transform.DOKill();
toggles[index].transform.DOShakeScale(0.3f, 0.5f);
}
});
}
}
#endregion
}
Base基类:所有UI界面都需要继承该类,便于统一管理
可以在基类中定义通用的显示隐藏动画,及其他UI通用函数
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIBase : MonoBehaviour
{
public bool isShow { get { return gameObject.activeSelf; } }
public virtual void Init(params object[] args)
{
//gameObject.SetActive(false);
}
public virtual void Destroy()
{
Destroy(gameObject);
}
public virtual void Show(params object[] args)
{
if (!gameObject.activeSelf)
gameObject.SetActive(true);
}
public virtual void Hide()
{
if (gameObject.activeSelf)
gameObject.SetActive(false);
}
public virtual void HideDelay(float delayTime)
{
if (delayTime <= 0)
Hide();
else
Invoke("Hide", delayTime);
}
}
Panel和Popup类
Panel面板:界面中只能同时显示一个Panel,显示下个Panel时需要隐藏当前Panel
Popup弹窗:界面中可以同时显示多个Popup,在显示多个Popup时可以控制子物体顺序,以此改变显示层级顺序
可以在Panel和Popup类中分别定义内部通用函数及显示隐藏动画
public class UIPanelBase : UIBase
{
}
public class UIPopupBase : UIBase
{
}
MessageNotifer:通知消息管理器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using System.Linq;
//弹窗消息类
public class MessageInfo
{
public string infoStr { get; private set; }
public Color color { get; private set; }
//持续显示时间
public float time { get; private set; }
public MessageInfo(string messageStr, Color messageColor, float showTime)
{
infoStr = messageStr;
color = messageColor;
time = showTime;
}
}
public class MessageNotifer : MonoBehaviour
{
#region --- Show Message Popup ---
[Header("Message Popup")]
[SerializeField] UINotifyMessageBar messagePopup;
public void ShowMessagePopup(string messageInfoStr)
{
ShowMessagePopup(new MessageInfo(messageInfoStr, Color.white, 10));
}
public void ShowMessagePopup(string messageInfoStr, Color messageInfoColor, float showTime)
{
ShowMessagePopup(new MessageInfo(messageInfoStr, messageInfoColor, showTime));
}
public void ShowMessagePopup(MessageInfo messageInfo)
{
if (messageInfo == null)
return;
messagePopup.ShowMessage(messageInfo);
}
public void ClearMessagePopup()
{
messagePopup.Clear();
}
#endregion
#region --- Show Message Bar ---
[Header("Message Bar")]
//最多显示数量
[SerializeField] int maxShowCount = 5;
[SerializeField] Transform messageNode;
//消息弹窗预设
[SerializeField] UINotifyMessageBar messageBarPrefab;
//待显示消息列表
Queue<MessageInfo> messageInfoQueue = new Queue<MessageInfo>();
//所有可用弹窗列表
List<UINotifyMessageBar> messageBarPool = new List<UINotifyMessageBar>();
// -----------
public void ShowMessageBar(string messageInfoStr)
{
ShowMessageBar(new MessageInfo(messageInfoStr, Color.black, 1));
}
public void ShowMessageBar(string messageInfoStr, Color messageInfoColor, float showTime)
{
ShowMessageBar(new MessageInfo(messageInfoStr, messageInfoColor, showTime));
}
public void ShowMessageBar(MessageInfo messageInfo)
{
if (messageInfo == null)
return;
messageInfoQueue.Enqueue(messageInfo);
List<UINotifyMessageBar> showMessageBarList = messageBarPool.FindAll(bar => bar.isShow);
if (showMessageBarList.Count < maxShowCount)
StartCoroutine(ShowMessageInfoBar());
}
IEnumerator ShowMessageInfoBar()
{
if (messageInfoQueue.Count == 0)
yield break;
MessageInfo toShowInfo = messageInfoQueue.Dequeue();
UINotifyMessageBar messageBar = GetEmptyMessagePopup();
if (messageBar == null)
yield break;
//设置子物体顺序, 即最新显示的弹窗在最上面
messageBar.transform.SetSiblingIndex(0);
yield return StartCoroutine(messageBar.StartShowMessage(toShowInfo));
messageBar.gameObject.SetActive(false);
yield return null;
if (messageInfoQueue.Count > 0)
StartCoroutine(ShowMessageInfoBar());
}
// ------
UINotifyMessageBar GetEmptyMessagePopup()
{
UINotifyMessageBar messageBar = null;
messageBar = messageBarPool.FirstOrDefault(bar => !bar.isShow);
if (messageBar == null)
{
messageBar = Instantiate(messageBarPrefab, messageNode);
if (messageBar != null)
messageBarPool.Add(messageBar);
}
if (messageBar != null)
messageBar.gameObject.SetActive(true);
return messageBar;
}
#endregion
}
UINotifyMessageBar:通知消息弹窗,在屏幕指定区域,展示通知消息,不可点击交互,由MessageNotifer统一管理,不在Panel和Popup范围内
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
public class UINotifyMessageBar : MonoBehaviour
{
public bool isShow { get; private set; }
CanvasGroup canvasGroup;
Text infoText;
//淡入/淡出时间
const float fadeTime = 0.5f;
void Awake()
{
canvasGroup = GetComponent<CanvasGroup>();
infoText = GetComponentInChildren<Text>();
Clear();
}
public void ShowMessage(MessageInfo messageInfo)
{
Clear();
StartCoroutine(StartShowMessage(messageInfo));
}
public IEnumerator StartShowMessage(MessageInfo messageInfo)
{
isShow = true;
canvasGroup.alpha = 0;
infoText.text = messageInfo.infoStr;
infoText.color = messageInfo.color;
//开始显示
canvasGroup.DOFade(1, fadeTime);
//持续一段时间
yield return new WaitForSeconds(fadeTime + messageInfo.time);
//开始隐藏
canvasGroup.DOFade(0, fadeTime);
yield return new WaitForSeconds(fadeTime);
canvasGroup.DOKill();
isShow = false;
canvasGroup.alpha = 0;
infoText.text = "";
}
public void Clear()
{
StopAllCoroutines();
canvasGroup.DOKill();
isShow = false;
canvasGroup.alpha = 0;
infoText.text = "";
}
}
此外,还可以增加可交互通用弹窗,继承Popup基类:
弹窗显示Title文字说明,有确认和取消两个按钮,每次展示时重新绑定确认/取消按钮事件,方便多个场景通用
实现比较简单,就不贴代码了
最后
以上就是寒冷丝袜为你收集整理的【Unity】简易UI框架(带通知弹窗)的全部内容,希望文章能够帮你解决【Unity】简易UI框架(带通知弹窗)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复