千锋教育-做有情怀、有良心、有品质的职业教育机构

当前位置:首页  >  关于学院  >  技术干货  >  Unity技术干货  >  正文

xlua-framework之UI框架

来源:千锋教育
发布时间:2022-09-28 17:58:00
分享

  前言

  xlua-framework

  xlua-framework-unity2018

  我们前面说过xlua-framework这个框架,是一个纯lua的一个框架,也就是说我们所有的逻辑都可以在lua中实现,只有资源模块和网络模块是c#原生写的,但是也在lua中给我们包装的工具类,让我们更方便的使用。在框架的纯lua代码中,不得不说,ui框架是我最喜欢的,一套基于mvc的一套ui框架。

  MVC框架

  说到MVC框架,很多人可能会说,mvc根本就不适合游戏,有这种想法的人,一定是个编程新手,我们在介绍UI框架前,先来介绍下MVC。

  首先,mvc,是一种编程思想或者说框架思想,并不是一个设计模式,而这种思想的核心是分层,也就是说,我们要把ui相关的界面显示和ui数据存储以及ui控制逻辑分开不同的文件来写,为什么要分层呢?这和Web的mvc思想是一致的,都是为了降低我们类的复杂度,方便我们阅读和扩展,如下图所示:

xlua-framework之UI框架1

 

  比如说,一个复杂的UI页面类,有2000多行代码。如果我们代码结构写的不好,会发现这个类很难维护,也很难扩展,甚至连阅读都很难,接下来我们针对上面这个UI做一个小优化:我们把UI控件显示相关的函数,独立到一个View类中,数据相关的放到Model类中,控制输入相关的放到Ctrl类中。接下来我们这个页面就很容易扩展和阅读了,比如我们只是修改ui显示相关的,那我们之控制View类就行了,大概也就4-5百行左右的代码,很好维护,同理,如果是想修改用户输入控制的方法,直接修改Ctrl类就行了,如果只是处理UI显示的数据相关,直接修改Model类中对数据整理相关的函数就可以了。

  MVC的变体

  1.MVC(Model-View-Controller)

  MVC是比较直观的架构模式,用户操作->View(负责接收用户的输入操作)->Controller(业务逻辑处理)->Model(数据持久化)->View(将结果反馈给View)。

  MVC使用非常广泛,比如JavaEE中的SSH框架(Struts/Spring/Hibernate),Struts(View, STL)-Spring(Controller, Ioc、Spring MVC)-Hibernate(Model, ORM)以及ASP.NET中的ASP.NET MVC框架,xxx.cshtml-xxxcontroller-xxxmodel。

xlua-framework之UI框架2

 

  2.MVP(Model-View-Presenter)

  MVP是把MVC中的Controller换成了Presenter(呈现),目的就是为了完全切断View跟Model之间的联系,由Presenter充当桥梁,做到View-Model之间通信的完全隔离。

  .NET程序员熟知的ASP.NET webform、winform基于事件驱动的开发技术就是使用的MVP模式。控件组成的页面充当View,实体数据库操作充当Model,而View和Model之间的控件数据绑定操作则属于Presenter。控件事件的处理可以通过自定义的IView接口实现,而View和IView都将对Presenter负责。

xlua-framework之UI框架3

 

  3.MVVM(Model-View-ViewModel)

  如果说MVP是对MVC的进一步改进,那么MVVM则是思想的完全变革。它是将“数据模型数据双向绑定”的思想作为核心,因此在View和Model之间没有联系,通过ViewModel进行交互,而且Model和ViewModel之间的交互是双向的,因此视图的数据的变化会同时修改数据源,而数据源数据的变化也会立即反应到View上。

  这方面典型的应用有.NET的WPF,js框架Knockout、AngularJS等。

xlua-framework之UI框架4

  xluaframework的MVC结构

  当请求UI管理器打开窗口时,UI管理器会根据UI配置找到MVC各层脚本文件并实例化对象,生成一个UIWindow,一个window包含了View,Model,Ctrl三个组件,但是也不是一定modle和ctrl都要有,如果你的页面非常简单,可以没有Model和Ctrl,或者只有Model没有Ctrl,只有Ctrl没有Model都可以。但是标准的页面我们是需要MVC相互配合来实现的。

  View层:负责界面所有UI刷新操作,只和展示相关的数据放在这,只有操作相关数据放Model去

  注意:

  1、被动刷新:所有界面刷新通过消息驱动—除了打开界面时的刷新

  2、对Model层可读,不可写—调试模式下强制

  3、所有写数据、游戏控制操作、网络相关操作全部放Ctrl层

  4、Ctrl层不依赖View层,但是依赖Model层

  5、任何情况下不要在游戏逻辑代码操作界面刷新—除了打开、关闭界面

  Model层:负责界面相关数据,同时负责消息定制和分发

  注意:

  1、数据大体分为两类:游戏逻辑数据、界面控制数据

  2、游戏逻辑数据:从游戏数据中心取数据,这里不做为数据源,只做中转和必要处理(如排序),游戏中心数据改动以后在这里监听变化

  3、界面控制数据:一般会影响到多个界面展示的控制数据,登陆界面显示当前服务器,当受到选服界面操作的影响

  4、界面Model层对View层是只读不写的,一定不要在View层写Model

  5、界面Model层不依赖Ctrl层和View层,意思是说拿掉这这两层代码,Model依旧能完好运行

  6、界面Model层数据只影响UI,不影响游戏逻辑,游戏逻辑不能从Model层取数据,意思是没有界面,游戏依旧能跑

  Ctrl层:负责发送网络请求(网络数据)、操作游戏逻辑、修改模型数据(本地数据)

  注意:

  1、UI控制层用于衔接Model层和View层,主要是用来修改数据,或者进行游戏逻辑控制

  2、修改数据:界面操作相关数据直接写Model层、游戏逻辑相关数据写数据中心

  3、游戏控制:发送网络请求、调用游戏控制逻辑函数

  4、Ctrl层是无状态的,不能保存变量–调试模式下强制

  UI脚本目录结构

  分成两个部分:LuaScripts/Framework/UI为UI框架代码,LuaScripts/UI为UI逻辑代码。其中:

  LuaScripts/Framework/UI/Base:基类

  LuaScripts/Framework/UI/Component:UI组件

  LuaScripts/Framework/UI/Message:UI消息定义

  LuaScripts/Framework/UI/Util:UI工具类

  LuaScripts/ UI/Config:窗口配置

  LuaScripts/ UI/UIxxx:UI逻辑模块,其中:Controller、Model、View对应控制、模型、视图脚本;而UIxxxConfig为模块配置脚本

  UI模块添加流程

  拼预设:如AssetsPackage/ UI/ Prefabs/ View/ UILogin.prefab

  UI名配置:LuaScripts/ UI/Config/ UIWindowNames中添加

  导入配置:LuaScripts/ UI/Config/ UIConfig中添加

  脚本配置:LuaScripts/ UI/UIxxx/UIxxxConfig中配置,需要注意的是:Model、Ctrl、View层如果没有实现脚本,则直接填写nil;PrefabPath为相对于AssetsPackage目录的路径,需要带文件名后缀

  在原框架xluaframework中,没有带ui的的自动创建工具,我们可以参考issues#39加一个工具加一个,xluaframework-unity2018的版本中已经带了这个工具,我们直接在菜单栏的Tools->MVC Tools打开UI创建面板

xlua-framework之UI框架5

 

  我们只需要根据自己的需要填上UI的名字和文件夹名字,然后选择是否需要Model和Ctrl,以及属于哪个层,最后点击CreateUILuaData按钮即可。

  UI工作流程

  当请求UI管理器打开窗口时,UI管理器会根据UI配置找到MVC各层脚本文件并实例化对象,生成一个UIWindow的数据结构标识一个窗口。立刻调度Model层OnEnable(首次打开先调用OnCreate),如果有传入参数,需要在此处保存下来;随后等待UI资源异步加载完毕,加载完毕后调度View层OnEnable(同样首次打开先调用OnCreate),View层随后实现类似Mono脚本的调度流程,View层可以随时读取Model层数据,但是写Model层数据需要经过Ctrl层;Ctrl层是无状态的,如果需要状态,写Model层就好。

  脚本调度顺序:

  OnCreate->OnEnable->Update->LateUpdate->OnDisable->OnDestroy

  注意:Update相关函数添加上就会被调度,尽量不用,节省性能。界面逻辑书写流程和写Mono脚本大概一致。

  数据流

  A) 打开窗口时传入数据:OnEnable中传入Model层保存

  B) Model层在OnEnable中从其他管理类或者数据类取数据并处理

  C) View层可存放自身控制数据,直接读、间接写Model层数据

  D) 模块与模块之间数据交换使用消息系统

  注意:更多参考MVC各个实现脚本中的说明;技术细节直接参考源代码。

  UI组件系统

  为了实现类似Mono脚本的函数调度,做了一个组件系统,脚本目录在LuaScripts/Framework/UI/Component。组件大概分为两种:基础组件、容器组件。

  基础组件是对Unity侧原生UI组件的封装,这层封装其实不要也行,只是封装后有些操作使用起来更加方便,比如图集图片切换;容器组件用于组合管理多个基础组件,并负责其中基础组件的函数调度。

  基础组件:

  UIButton,UICanvas,UIEffect,UIImage, UILayer,UIInput,UISlider,UIText,不做介绍,自己看源码

  容器组件:

  UITabGroup,UIButtonGroup,UIWrapGroup,不做介绍,自己看源码

  自定义组件:

  这里的自定义组件是指继承了UIBaseComponent的类,相当于子模块组件,对于十分复杂的UI界面,可以将模块独立的部分分离出来,写一个Component脚本(继承自UIBaseContainer),如主界面的小地图,如背包中的某个Item。这个Component类似Unity中的Mono脚本,挂上去就能用。

  使用示例参考选服界面服务器列表中每个Item的刷新逻辑,那里把每个Item当做了一个Component去刷新。

  View层脚本:

  View层脚本是最上层的容器组件,管理视图中所有组件的调度。

  特别需要注意的一点是:凡是Unity中的对象,在lua中进行判空时,不能直接判断是否等于nil,而必须使用IsNull方法来判断,这一点在XLua文档中也提到过。

  UI层级管理

  UI层级下的所有窗口根据OderInLayer的值来前后排布,为了避免层级混乱,这里进行统一管理,划分了一个子层级的概念,专供UI使用:

xlua-framework之UI框架6

  目前一共划分了6个子层级,第一个LuanchLayer只在启动界面使用;其余的子层级从上到下,展示时依次从背面到前面。

  SceneLayer:用于场景UI

  BackgroudLayer:背景UI

  NormalLayer:普通一级、二级、三级UI

  InfoLayer:信息UI

  TipLayer:提示UI

  TopLayer:顶层UI

  归属于下一个子层级的UI窗口总是会盖住上一个子层级的UI窗口,不管打开顺序如何;而归属于同一个子层级的多个UI,其层级关系由打开的先后顺序决定,后打开的UI总是会盖住先打开的UI。

  每两个相连子层级之间的OrderInLayer相间1000,而相同子层级的相连窗口OrderInLayer相间10,意思是说每个子层级最多可以同时打开100个窗口;而窗口内部还可以各自划分10个层级来使用,用于各个UI组件之间的层次关系(这些数值都可以根据具体情况调整配置)。在UGUI中,同属于同一个OrderInLayer的UI组件也可以排布先后,这种先后关系通过Hierarchy中的上下次序来决定,所以建议优先通过这种方式来排布先后,如果不能满足需求,再来使用不同的OrderInLayer来排布(会增加drawcall)。

  有关窗口组件层级的示例代码参考登陆界面的相关示例,代码脚本路径:LuaScripts/ UI/UILogin/View/UILoginView.lua。这里展示了文字特效复杂的参差关系,如果需要扩展,可参考UICanvas组件代码。

  总上所述

  总的来说,这个mvc结构的UI框架是一个非常棒的ui结构,我非常的喜欢,也在我公司内部进行了推广,大家现在都已经熟练使用了这个结构。不过最开始大家也不是很习惯,使用过程中还是碰到过很多问题的,比如:

  1.大家感觉页面拆开写很麻烦,虽然创建了Model和Ctrl但是里面都是空的:什么事总有第一次,永远不尝试,你就永远无法进步。等你写的多了,熟练了,才能慢慢掌握mvc的精髓。

  2.大家感觉Ctrl和Model中不能直接访问View很不方便:建议大家把上面的MVC简介再好好看看,我们既要分层也要注意解耦,如果MVC之间来回调用,会让你的页面耦合度增加,维护起来更麻烦。

  demo示例

  下面我们展示一个非常简单的一个例子:

xlua-framework之UI框架7+

xlua-framework之UI框架8-

  UILoginModel.lua

xlua-framework之UI框架9+

xlua-framework之UI框架10-

  UILoginCtrl.lua

xlua-framework之UI框架11+

xlua-framework之UI框架12-

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。

相关推荐

  • fps低怎么办?什么原因导致的? 低帧率(FPS)通常是指在实时图像渲染或视频播放过程中,每秒显示的帧数较低,导致画面不流畅或卡顿。下面是一些可能导致低帧率的原因和相应的解决方法:1.硬件性能不足:如果计算机或设备的处理能力不够强大,
  • fps低了怎么调高 要提高FPS(FramesPerSecond,每秒帧数)的性能,可以尝试以下方法:1.优化图形设置:降低图形质量和特效,如分辨率、纹理质量、阴影等。这会减少图形渲染的工作量,提高性能。2.关闭后台进程
  • 反射的实现原理? Load(“程序集”)加载程序集,返回类型是一个Assembly,得到程序集中所有类的名称,foreach (Type type in assembly.Type type = assembly.创建此类型实例,MethodInfo mInfo = type.
  • unity如何接入puerts webpack适用于我们执行ts编译为js用的插件,把需要的依赖加入到dependencies标签中,然后在vscode的终端输入npm install 拉取依赖即可,拉取成功后,会生成一-个node_ modules的文件夹,里面就是我们拉取的依赖库,可能很大,这个文件夹最好加入到忽略列表中。代码如下所示:
  • xlua-framework之UI框架 我们前面说过xlua-framework这个框架,是一个纯lua的一个框架,也就是说我们所有的逻辑都可以在lua中实现,只有资源模块和网络模块是c#原生写的,但是也在lua中给我们包装的工具类,让我们更方便的使用。在框架的纯lua代码中,不得不说,ui框架是我最喜欢的,一套基于mvc的一套ui框架。
  • xlua-framework之网络框架 一般我们说到网络框架,主要是指Socket网络框架,如果是Http的话,我们没有必要单独介绍了,简单用可以直接使用WWW或者UnityWebRequest,如果稍微复杂的使用,可以使用RestSharp库。所以我们本章主要讨论的是xlua-framework框架是如何实现socket网络框架的。