U3DFrameWorkDemo:五、UI模块
代码参考
代码文件参考下述详解的类图,工程参考第零章工程说明
概述
99.99%游戏甚至其他App都会有UI(UserInterface 用户交互接口),在比较复杂的UI系统中,为了方便开发和维护,通常会采用某些成熟的框架结构为主要指导思想进行开发,例如MVC、MVVM、MVP等等。在此项目中,以复用性为主要出发点采用MVVM的框架思想。
思路
- 为了提高开发效率和热更考虑,UI的业务采用Lua脚本,要建立Lua和Mono脚本的交互机制,同时也要考虑由此产生的效率问题
- 效率问题的总体思路:
- 尽量减少交互
- 尽量互相的引用
- 效率问题的总体思路:
- UI层级可能是不一样的,例如主界面在下面,背包面板在主界面上面,物品详情Tips在最上面
- UI弹出方式可能不一样,例如从副本选择界面进入副本详情界面时,打开副本详情界面自动关闭副本选择界面,而浏览副本详情界面发现对此没有兴趣管理时,关闭副本详情界面时自动打开副本选择界面。
- 这种类型UI使用栈型结构管理
- MVVM框架的消息机制,即当ViewModel的变量在变化时要抛出消息通知View层更新
- 业务复用逻辑,例如多个界面都需要显示玩家职业Icon,没必要每次都有根据职业ID去计算图片资源,可以定义复用的根据ViewModel的变量更新自动化处理View更新的类型
- 在View关闭时要确定取消消息监听,避免浪费资源
详解
UI模块
- ViewID:具体某个UI的ID索引
- ViewConfig:UI的配置信息,包含:预制体路径、层级、弹出类型等
- ViewFactory:View脚本的创建和缓存池管理
- ViewMgr:View脚本的创建和管理
- ViewMgr(CS):CSharp侧View(GameObj)创建和管理
- View:该View显示更新控制,View更新实现由其绑定的CSharp侧完成,其多部分功能由聚合的各种Register、Binder组件完成。
- View(CS):CSharp侧View的Mono脚本,实现Lua侧更新View的命令
- BinderRegister:托管该View的Binder的注册/反注册管理,在UI打开时注册,关闭时反注册。
- EventRegister:管理Event,与BinderRegister类似
- TimerRegister:管理Timer,与BinderRegister类似
- BindableDec:对类型进行可绑定变量更新广播的功能增加,通过Lua的__newindex元方法实现和BindableProperty类实现
- ViewModel:View数据模型,存放View相关数据,如个人信息界面玩家的ID,职业ID等,数据更新时通过聚合的BindableProperty广播给关心的Binder
- BindableProperty:由上层(ViewModel等)驱动更新数据,数据变化是广播给所有监听者
- UIBinder:监听到VM属性变化消息时多态的进行相关逻辑处理,如:
- UIBinderSetImage:根据资源路径设置图片
- UIBinderSetProfIcon:根据职业ID设置图片职业Icon
- UIBinderSetProfName:根据职业ID设置文本职业名
- UIAdapter:对某些C#侧Mono脚本的接口适配,例如更新列表的Binder适配列表控件、树形控件的更新接口
- UIUtil:调用C#侧的工具方法,主要是一些消耗性能操作的优化,如:ProfIconGameObj.Transform.Position = U3D.Vector3(x,y,z) 换成 UIUtil.SetPosition(view, widgetName, x, y, z)
主要生命周期流程
- 反注册相关操作在基类完成,避免业务忘记导致浪费性能和bug
- 可以在OnInit和OnStart引用别的对象,避免循环引用的问题
备注
- Binder这套消息处理思路也会推广到其他业务,参考之前文章跳转链接:类暗黑破坏神属性系统思路
- Lua面向对象UI模块甚至整个lua侧的业务基础,实现可以参考之前的文章跳转链接:Lua 面向对象&支持虚函数