前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Unity面向对象思想搭建UI面板代码思路

Unity面向对象思想搭建UI面板代码思路

原创
作者头像
晨星成焰
发布2024-12-03 12:04:07
发布2024-12-03 12:04:07
1160
举报
文章被收录于专栏:Unity

前言

最近学习了两个unity进阶点的项目

看了下它们的UI搭建思路普遍都是这样实现,遂做记录。

构造一个UI管理器,去管理面板基类衍生出的各个UI面板预设体,通过管理器动态加载各个UI面板在UI场景里

UI管理器类

代码语言:csharp
复制
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;
        }
    }
   
}

面板基类

代码语言:csharp
复制
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

代码语言:csharp
复制
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

代码语言:csharp
复制
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同理

将OnePanel打包成预制体

在Unity的Assets里新建一个Resources文件夹

将OnePanel面板和SecondPanel面板拖入Resources其中打包成预制体

接着可以删除原Canvas下的OnePanel 和 SecondPanel了

简单效果演示

新建一个空对象Main,用来搭载类似入口函数的Main脚本

代码语言:csharp
复制
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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • UI管理器类
  • 面板基类
  • 预设体搭建
    • 在场景里的画布新建两个测试面板,一个用来做最开始的界面,一个用来切换
    • 将OnePanel打包成预制体
  • 简单效果演示
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档