GameFramework——UI

前言

刚开始做游戏时,大家就说入行了都是UI仔,证明了UI的重要性,导致我对UI框架一直有一种畏惧的心理。
这次就从GF的UI加载来简单看看GF的UI框架以及它的使用
在这里给大家推荐我们群主写的GF解析,写的非常好
传送门

打开UI界面

第一视角分析,找到ProcedureMenu.cs
首先订阅一个UI成功打开的事件,接下来就是一个OpenUIForm函数
在这里插入图片描述
我们继续往上,还需要往上。此处int?代表可空类型,如果没有赋值会返回null而不是0
在这里插入图片描述
此处我们通过读取配置表,并且加上前置路径,继续往上看
在这里插入图片描述

在这里插入图片描述
此处是UI组件调用UIManager.OpenUIForm方法
在这里插入图片描述
UIManager属于逻辑层也就是GF层面的了,我们继续看源码。此处的逻辑是从对象池获取UI实例,如果对象池中没有
就先在 m_UIFormsBeingLoaded字典中记录,这个字典记录的应该是正在加载的UIForm,然后通过ResourceManager来异步加载对应资源,我们在LoadAsset时还传入了加载成功时的回调方法
此回调的逻辑是从m_UIFormsBeingLoaded移除该UI的id
在这里插入图片描述
再通过UIFormInstanceObject.Create()创建出对应UI实例,通过对象池进行注册,最后调用InternalOpenUIForm方法
如果一开始对象池没有记录,就直接调用InternalOpenUIForm方法

/// <summary>
        /// 打开界面。
        /// </summary>
        /// <param name="uiFormAssetName">界面资源名称。</param>
        /// <param name="uiGroupName">界面组名称。</param>
        /// <param name="priority">加载界面资源的优先级。</param>
        /// <param name="pauseCoveredUIForm">是否暂停被覆盖的界面。</param>
        /// <param name="userData">用户自定义数据。</param>
        /// <returns>界面的序列编号。</returns>
        public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, bool pauseCoveredUIForm, object userData)
        {
            if (m_ResourceManager == null)
            {
                throw new GameFrameworkException("You must set resource manager first.");
            }

            if (m_UIFormHelper == null)
            {
                throw new GameFrameworkException("You must set UI form helper first.");
            }

            if (string.IsNullOrEmpty(uiFormAssetName))
            {
                throw new GameFrameworkException("UI form asset name is invalid.");
            }

            if (string.IsNullOrEmpty(uiGroupName))
            {
                throw new GameFrameworkException("UI group name is invalid.");
            }

            UIGroup uiGroup = (UIGroup)GetUIGroup(uiGroupName);
            if (uiGroup == null)
            {
                throw new GameFrameworkException(Utility.Text.Format("UI group '{0}' is not exist.", uiGroupName));
            }

            int serialId = ++m_Serial;
            //从对象池获取UI实例
            UIFormInstanceObject uiFormInstanceObject = m_InstancePool.Spawn(uiFormAssetName);
            //如果对象池不存在就loadAsset
            if (uiFormInstanceObject == null)
            {
                //在字典中记录
                m_UIFormsBeingLoaded.Add(serialId, uiFormAssetName);
                //异步加载资源
                m_ResourceManager.LoadAsset(uiFormAssetName, priority, m_LoadAssetCallbacks, OpenUIFormInfo.Create(serialId, uiGroup, pauseCoveredUIForm, userData));
            }
            else
            {
                InternalOpenUIForm(serialId, uiFormAssetName, uiGroup, uiFormInstanceObject.Target, pauseCoveredUIForm, false, 0f, userData);
            }

            return serialId;
        }

InternalOpenUIForm

此函数的作用是调用UIForm.OnInit,然后加入对应的UIGroup中,然后调用UIForm.OnOpen,最后UIGroup.Refresh即刷新界面组
在这里插入图片描述

关闭UI界面

从UIGroup移除,调用UIForm.OnClose方法,调用Refresh
最后分别是调用关闭完成的回调、将此UIForm加入m_RecycleQueue中,加入此队列的原因是在下一次Update中会取出所有UIForm,调用其界面回收函数以及让对象池回收
在这里插入图片描述
在这里插入图片描述

GF的UI架构

  • IUIManager
  • IUIGroup
  • IUIForm
  • UIManager
  • UIGroup
  • UIForm
  • UIFormLogic
  • UguiForm
  • UIFormInfo

这只是一部分,其中继承、组合、相互引用就已经比较复杂了
和Form相关I开头的接口均属于GF层,直接继承自这些接口类属于UGF层,最后UguiForm以及继承自UguiForm均属于游戏业务层(根据需求也可以自己写为GuiForm)
和Manager相关的包括UIGroup都属于GF层,需要看源码才能学习到

UIGroup

继承自IUIGroup,UIManager的内部类,当有多个UIForm处于同一Group,可以用UIGroup来控制它们的层级、轮询每个Form的Update。
虽然没有用过,但我认为如果有BagForm和ItemForm也就是背包和物品的话,就可以归为一个Group,因为它们同一时刻就一个处于最上层且两者之间有关联。
UIGroup直接受UIManager管理,各个UIGroup管理各自的UIForm。(开头传送门写的,写的真好)

在这里插入图片描述
其中有一个链表,里面记录了属于此UIGroup的UIFormInfo(和UIForm相互引用)

对外开放的属性

  • Name:名字
  • Depth:深度,Set也开放,完成后Refresh()
  • Pause:是否暂停,Set也开放,完成后Refresh()
  • UIFormCount:包含的界面数量
  • CurrentUIForm:当前界面
  • Helper:界面辅助器

RefocusUIForm

在这里插入图片描述
直接将此UIForm放在链表头

Refresh

代码太长啦就不截图啦
刷新界面组,不难理解就是比较繁琐。举个栗子就是如果当前UIGroup暂停的但是当前链表第一个UIForm没有暂停就将其暂停,如果UIGroup没被覆盖但是UIForm被覆盖了就将它取消覆盖

UIFormInfo

UIGroup的内部类,UIGroup链表中记录的类就是UIFormInfo而不是UIForm,因为UIFormInfo中有包含UIForm的引用,其中有UIForm没有记录的两个状态Paused和Coverd,相当于对UIForm又封装了一层,所以我们拿到UIFormInfo就等于拿到了UIForm

UIForm

UI界面类,被UIGroup管理,属于UGF层(引用了Unityengine)可以看得到代码。

  • SerialId:界面序列编号(不理解干啥的,大佬的文章是说用于标识相同UI的不同实例和用于区别放回对象池前和再次取出的情况)
  • UIFormAssetName:资源名称
  • Handle:界面实例,Object类,因为UIManager也需要对其操作,如果是GameObj则无法操作因为其属于GF层
  • UIGroup:界面所属的界面组
  • DepthInUIGroup:界面深度(在所属Group中的)
  • PauseCoveredUIForm:为Ture则代表打开时在其下面的UI全部Pause,关闭时下面的UI全部Resume
  • Logic:UIFormLogic类,界面逻辑。需要被UguiForm所继承
    然后还有些生命周期方法和深度相关的方法

UguiForm

继承自UIFormLogic,也就是用于编写逻辑的,如果要自己编写UI界面的逻辑,就要继承自UguiForm
在这里插入图片描述
在这里插入图片描述

结构就是如此,一个Form上又要挂载UI界面类记录obj又要挂载逻辑类。这些Form均为预制物,比如button的点击事件都是手动设置而不是靠代码设置的。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值