前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unity MVC丨(五)完善View视图层基类:BaseWindow

Unity MVC丨(五)完善View视图层基类:BaseWindow

作者头像
星河造梦坊官方
发布2024-08-15 19:01:32
730
发布2024-08-15 19:01:32
举报
文章被收录于专栏:星河造梦坊专栏

大家好,我是SKODE。 小提示:选中左侧目录,可快速找到所需内容

本系列博客地址:传送门

一、为什么要完善?

首先说说,为什么要这样做呢。

首先说下当前基类,在我们在团队配合时,可能遇到问题:

  • 你当前声明的基础属性是protected的,不允许跟你配合的队友访问,那你的队友该怎样知道这些属性的值呢?
  • 若你为了解决上个问题,将基础属性改为public,若你的队友是新手,有没有会误改了你的值的可能?
  • 我们该基类没有继承Mono,没有Awake、OnEnable等生命周期,那我们写的虚方法Awake、OnEnable什么时候执行呢?

二、完善 BaseWindow 的思路

好,我们现在就挨个解决一下上面的问题。

1、你当前声明的基础属性是protected的,不允许跟你配合的队友访问,那你的队友该怎样知道这些属性的值呢?

我们声明如下这样的方法,队友只能得到,不能修改。

2、我们该基类没有继承Mono,没有Awake、OnEnable等生命周期,那我们写的虚方法Awake、OnEnable什么时候执行呢?

我们新增加:

打开窗体、关闭窗体、预加载窗体 等接口,供外部调用。

我们在这三个接口中,调用我们写的Awake、OnEnabl等虚方法,完成该UI窗体的初始化、关闭等生命周期。

三、最终代码

代码语言:javascript
复制
using UnityEngine;
using UnityEngine.UI;

namespace MVCLibrary.View
{
    public class BaseWindow
    {
        //定义用到的属性(因为我们现在不继承Mono了,所以需要自己定义)

        #region 基础属性

        /// <summary>
        /// UI物体
        /// </summary>
        protected Transform transform;

        /// <summary>
        /// 资源名称(UI预制体的存放路径)
        /// </summary>
        protected string resName;

        /// <summary>
        /// 是否常驻(若不是常驻,只用一次,那么便关闭后,就将其销毁掉)
        /// </summary>
        protected bool resident;

        /// <summary>
        /// 是否可见
        /// </summary>
        protected bool visable = false;

        /// <summary>
        /// 窗体类型
        /// </summary>
        protected WindowType selfType;

        /// <summary>
        /// 场景类型
        /// </summary>
        protected SceneType sceneType;

        #endregion


        #region UI控件

        /// <summary>
        /// 按钮列表
        /// </summary>
        protected Button[] buttonList;

        #endregion


        #region 需要给子类提供的接口

        /// <summary>
        /// 初始化
        /// </summary>
        protected virtual void Awake()
        {
            buttonList = transform.GetComponentsInChildren<Button>(true);
            RegisterUiEvent();
        }

        /// <summary>
        /// UI事件的注册
        /// </summary>
        protected virtual void RegisterUiEvent()
        {
        }

        /// <summary>
        /// 添加事件
        /// </summary>
        protected virtual void OnAddListener()
        {
        }

        /// <summary>
        /// 移除事件,触发移除所有的游戏事件
        /// </summary>
        protected virtual void OnRemoveListener()
        {
        }

        /// <summary>
        /// 每次打开,触发了添加的打开事件
        /// </summary>
        protected virtual void OnEnable()
        {
        }

        /// <summary>
        /// 每次关闭,触发了添加的隐藏事件
        /// </summary>
        protected virtual void OnDisable()
        {
        }

        /// <summary>
        /// 每帧更新
        /// </summary>
        /// <param name="deltaTime">两帧间隔的时间</param>
        protected virtual void Update(float deltaTime)
        {
        }

        #endregion


        #region 窗体管理方法

        /// <summary>
        /// 打开窗体
        /// </summary>
        public void Open()
        {
            if (transform == null)
            {
                if (Create())
                    Awake();
            }

            if (transform.gameObject.activeSelf == false)
            {
                //将自身设置到 workstation 下,因为是 SetParent ,所以设置位置后,本物体层级始终在workstation最后面,就保证了本物体始终不会被其他物体遮挡。
                UIRoot.SetParent(transform, true, selfType == WindowType.TipsWindow);
                transform.gameObject.SetActive(true);
                visable = true;
                OnEnable();
                OnAddListener();
            }
        }


        /// <summary>
        /// 关闭窗体
        /// </summary>
        /// <param name="isForceClose">是否强制卸载掉(销毁)该窗体</param>
        public void Close(bool isDestroy = false)
        {
            if (transform.gameObject.activeSelf)
            {
                OnRemoveListener();
                OnDisable();

                if (isDestroy)
                {
                    if (resident)
                    {
                        transform.gameObject.SetActive(false);
                        
                        //将本UI设置到 recyclePool 回收池中
                        UIRoot.SetParent(transform,false,false);
                    }
                    else
                    {
                        GameObject.Destroy(transform.gameObject);
                        transform = null;
                    }
                }
                else
                {
                    GameObject.Destroy((transform.gameObject));
                    transform = null;
                }
            }

            visable = false;
        }

        /// <summary>
        /// 预加载窗体
        /// </summary>
        public void PreLoad()
        {
            if (transform == null)
            {
                if (Create())
                    Awake();
            }
        }

        /// <summary>
        /// 供外部调用,获得该UI的场景类型
        /// </summary>
        public SceneType GetSceneType()
        {
            return sceneType;
        }

        /// <summary>
        /// 供外部调用,获得该UI窗体类型
        /// </summary>
        public WindowType GetWindowType()
        {
            return selfType;
        }

        /// <summary>
        /// 获得该窗体根节点
        /// </summary>
        public Transform GetRoot()
        {
            return transform;
        }

        /// <summary>
        /// 获得该窗体当前是否可见
        /// </summary>
        public bool IsVisable()
        {
            return visable;
        }

        /// <summary>
        /// 获得该窗体是否常驻
        /// </summary>
        public bool GetResident()
        {
            return resident;
        }

        /// <summary>
        /// 创建UI窗体
        /// </summary>
        /// <returns>是否创建成功</returns>
        private bool Create()
        {
            if (string.IsNullOrEmpty(resName))
            {
                return false;
            }

            if (transform == null)
            {
                var obj = Resources.Load<GameObject>(resName);
                if (obj == null)
                {
                    Debug.LogError($"未找到预制件{selfType}");
                    return false;
                }

                transform = GameObject.Instantiate(obj).transform;

                transform.gameObject.SetActive(false);

                UIRoot.SetParent(transform, false, selfType == WindowType.TipsWindow);

                return true;
            }

            return true;
        }

        #endregion
    }

    /// <summary>
    /// 窗体的类型
    /// </summary>
    public enum WindowType
    {
        LoginWindow, //登录窗体
        StoreWindow, //商城窗体
        TipsWindow //提示窗体
    }

    /// <summary>
    /// 场景的类型,目的是提供根据场景类型,进行预加载
    /// </summary>
    public enum SceneType
    {
        None, //空场景
        Login, //登录场景
        Battle //对战场景
    }
}

现在能看出来,MVC逻辑清晰,适合团队配合,

但体量确实大,方法都要自己写,不能可视化,小项目用这样的框架确实大材小用。

但我们之所以能济济一堂,坐在这里,开始一场伟大的学习

不就是因为我们要升职加薪进大公司嘛

所以感谢我们的MVC框架开发者🤗

因为要恰饭,在此推荐下我们一个人完成的项目,可以使用DoozyUI插件进行开发,MVC的这些逻辑还需要我们写吗?不存在的。

DoozyUI:传送门

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-07-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、为什么要完善?
  • 二、完善 BaseWindow 的思路
  • 三、最终代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档