最近学习了两个unity进阶点的项目
看了下它们的UI搭建思路普遍都是这样实现,遂做记录。
构造一个UI管理器,去管理面板基类衍生出的各个UI面板预设体,通过管理器动态加载各个UI面板在UI场景里
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIManager
{
private static UIManager _instance = new UIManager();
public static UIManager Instance => _instance;
//存储面板的容器
private Dictionary<string, BasePanel> _panelDic = new Dictionary<string, BasePanel>();
//获取父对象
private Transform _canvasTrans;
private UIManager()
{
//得到场景上创造好的Canvas对象
_canvasTrans = GameObject.Find("Canvas").transform;
//让Canvas对象过场景不消除
//通过动态创造和动态加载的对象,通过DontDestroyOnLoad方法,让动态创造的对象过场景不消除
GameObject.DontDestroyOnLoad(_canvasTrans.gameObject);
}
//显示面板
public T ShowPanel<T>() where T : BasePanel
{
//保证泛型T的类型和面板名一直
string panelName = typeof(T).Name;
//判断容器中是否有这个面板,如果有直接返回
if (_panelDic.ContainsKey(panelName)) return _panelDic[panelName] as T;
//显示面板 动态创造面板预设体 设置父对象
//根据得到的类名及预制体面板名 动态创造面板
//Resources.Load<GameObject>(panelName)
GameObject panelObj = GameObject.Instantiate(Resources.Load<GameObject>(panelName));
panelObj.transform.SetParent(_canvasTrans, false);
//获取面板
T panel = panelObj.GetComponent<T>();
//把面板脚本存储到对应容器字典中 方便之后获取
//_panelDic[name] = panel;
_panelDic.Add(panelName, panel);
//调用显示自己的逻辑
panel.ShowMe();
return panel;
}
//隐藏面板
//参数一: 是否渐隐
public void HidePanel<T>(bool isFade = true) where T : BasePanel
{
//根据泛型T得到类名
string panelName = typeof(T).Name;
//判断容器中是否有这个面板
if (_panelDic.ContainsKey(panelName))
{
if(isFade)
{
_panelDic[panelName].HideMe(() =>
{
//淡出成功后,删除面板
GameObject.Destroy(_panelDic[panelName].gameObject);
//移除面板
_panelDic.Remove(panelName);
});
}
else
{
//不淡出直接删除面板
GameObject.Destroy(_panelDic[panelName].gameObject);
//移除面板
_panelDic.Remove(panelName);
}
}
}
//获得面板
public T GetPanel<T>() where T : BasePanel
{
//根据泛型T得到类名
string panelName = typeof(T).Name;
//判断容器中是否有这个面板
if (_panelDic.ContainsKey(panelName))
{
return _panelDic[panelName] as T;
}
else
{
return null;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public abstract class BasePanel : MonoBehaviour
{
//淡入淡出控制组件
private CanvasGroup _canvasGroup;
//淡入淡出的速度
private float _alphaSpeed = 10;
private bool _isShow = false;
//淡出成功时,要执行的委托函数
private UnityAction _hideCallBack;
protected virtual void Awake()
{
_canvasGroup = this.GetComponent<CanvasGroup>();
if(_canvasGroup == null)
{
Debug.LogError("面板未添加CanvasGroup组件");
_canvasGroup = this.gameObject.AddComponent<CanvasGroup>();
Debug.Log("添加CanvasGroup组件");
}
}
// Start is called before the first frame update
protected virtual void Start()
{
Init();
}
/// <summary>
/// 初始化面板 按钮事件监听等等内容
/// </summary>
public abstract void Init();
/// <summary>
/// 显示面板
/// </summary>
public virtual void ShowMe()
{
_isShow = true;
_canvasGroup.alpha = 0;
}
/// <summary>
/// 隐藏面板
/// </summary>
public virtual void HideMe(UnityAction hideCallBack)
{
_isShow = false;
_canvasGroup.alpha = 1;
//淡出成功的回调实现
_hideCallBack = hideCallBack;
}
// Update is called once per frame
void Update()
{
//淡入淡出实现
if(_isShow && _canvasGroup.alpha != 1)
{
//淡入
_canvasGroup.alpha += Time.deltaTime * _alphaSpeed;
if(_canvasGroup.alpha >= 1)_canvasGroup.alpha = 1;
}
else if( !_isShow && _canvasGroup.alpha != 0)
{
//淡出
_canvasGroup.alpha -= Time.deltaTime * _alphaSpeed;
if(_canvasGroup.alpha <= 0)
{
_canvasGroup.alpha = 0;
//TODO传入一个委托函数删除自己
_hideCallBack?.Invoke();
}
}
}
}
因为我加入了淡入淡出的功能,所以记得给Panel加CanvasGroup组件,不加的话,代码里会自动加上,但是会有报错信息
OnePanel.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class OnePanel : BasePanel
{
//只需要绑定 按钮
public Button btnToggle;
public override void Init()
{
//初始化 按钮事件监听
btnToggle.onClick.AddListener(() =>
{
//通过UI管理器隐藏OnePanel面板
UIManager.Instance.HidePanel<OnePanel>();
UIManager.Instance.ShowPanel<SecondPanel>();
});
}
}
SecondPanel.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SecondPanel : BasePanel
{
//只需要绑定 按钮
public Button btnToggle;
public override void Init()
{
//初始化 按钮事件监听
btnToggle.onClick.AddListener(() =>
{
//通过UI管理器隐藏OnePanel面板
UIManager.Instance.HidePanel<SecondPanel>();
UIManager.Instance.ShowPanel<OnePanel>();
});
}
}
将OnePanel脚本拖给对应的OnePanel面板并将对应控件加入
SecondPanel同理
在Unity的Assets里新建一个Resources文件夹
将OnePanel面板和SecondPanel面板拖入Resources其中打包成预制体
接着可以删除原Canvas下的OnePanel 和 SecondPanel了
新建一个空对象Main,用来搭载类似入口函数的Main脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Main : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
//显示第一个面板
UIManager.Instance.ShowPanel<OnePanel>();
}
// Update is called once per frame
void Update()
{
}
}
运行前
运行后
点击按钮后
至此完结
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。