制作一个承载想法的东西(十)—— Lua侧的UI模块

  • A+
所属分类:Unity3d

参考模仿:smilehao/xlua-framework: Unity游戏纯lua客户端完整框架---基于xlua,整合tolua的proto-gen-lua以及各个lua库和工具类 (github.com)

在Lua侧实现了像Unity那样的组件的方式,有两个概念,组件和容器,基础的组件就类似Unity中继承了MonoBehaviour的脚本,基础容器就类似于Unity的GameObject上挂载着一管理自己和子物体组件的组件。所以容器有着组件的所有功能,并额外添加了获取组件的方法,lua侧认为为添加。

 

一、组件

在Unity中组件可以访问transform、gameobject,修改基础的显示隐藏、改变位置、改变旋转、改变缩放等等,所以基础的组件就可以仿照着实现这些获取和方法。

 

基础的组件,一般不会直接使用,使用容器进行添加,基础组件的构造函数需要提供持有者就是哪个容器持有这个组件,第二个参数对应的就是容器下的哪个物体,重载参数可以是组件所在的子物体路径、子物体索引、组件的gameobject、lua侧组件实例。

通过元表的形式提供获取transfrom、gameobject,不需要构造的时候就获取,需要时按需获取。还有管理一些基础的激活状态,提供方法给容器调度,基础的修改transfrom方法等。

 

UI基础组件(UGUI),在基础组件的基础之上,添加了针对RectTransform获取和操作方法:

 

二、容器

因为容器也可以认为是一个基础组件,因为UI组件添加了RectTransform,所以容器也分为了基础容器和UI容器,如果有其他的扩展组件,也需要扩展容器,这里说一下UI容器,继承UIBaseComponent.lua,基础容器是类似的。

这里重写了一些生命周期方法,定义存储组件的table,在显示和隐藏的时候调度组件提供的可用不可用调度方法。可以看到脚本前面引入了BaseContainerInterface,其实就是遍历方法复制过来,相当于接口,因为基础容器也是同一套代码,所以定义为一些接口来引用。

容器主要管理组件和记录持有的组件,lua添加组件对应着组件构造的四个重载,持有者就是自己,这样就对应上了。其他的获取组件,移除组件等等就是对记录的修改了和组件的释放了。

 

三、UI层级构建

说白了就是构建一个列表的有层级差的Canvas提供ui界面挂载渲染,所以需要一个配置表,Canvas的渲染模式使用相机的渲染方式,这样可以做多个相机且多个Canvas的层级关系,多个相机的形式可以针对有些东西需要渲染在ui和ui之间,这样的层级关系就可以处理好这些了。

首先我们需要一个配置,来说明这些层级关系的构建,CameraDepth就是相机的渲染层级,UILayers就是在当前相机下渲染的Canvas,多个相机结构可以在数组中再添加一个类似的配置,注意的是Layer的名字不要重复,以为UI管理是通过名字来识别是哪一个Canvas的。

 

好了,有了构建的配置表,下面就可以开始构建了,在UIManager单例实例化的时候,就可以遍历配置进行生成了。定义一个变量存储所有的Layer层,SetUIbuildConfig中针对每个相机下的Canvas进行生成。UIRoot是一个只包含一个相机子物体的预制体,在UIBuildGenerator中,获取到相机,并设置它的渲染层级,针对layer进行排序,并新建GameObject在UIRoot下,并实例化一个UILayer组件,在组件中进行相应的Canvas设置,并记录生成的layer,记录的layer是不管是哪个相机显然的。

 

在UILayer组件中,对实例化的GameObject添加相应的组件,让其成为Canvas。操作c#侧添加Canvas、CanvasScaler、GraphicRaycaster组件,并对其进行相应的设置,相应的设置可以看代码,针对需求进行设置。

 

四、UI窗口定义

定义一个记录一个窗口需要的信息类,每一个UI窗口记录,都用这个来保存。

 

再定义一个基础的窗口类,所有的UI界面都继承它,而基础的窗口类继承UIBaseContainer,也就是说UI界面就是一个组件同时也是一个容器,可以获取子物体的组件进行逻辑处理了。VIEW_CONFIG配置的是UI界面应该挂载在上面生成好的哪一个Layer下,PrefabPath是一个Addressable的地址,用来加载UI界面的预设。

 

五、UI管理器

UI管理器的作用就是打开界面和关闭界面等进行界面管理,打开界面的时候只要传入继承自UIBaseView的lua路径,这里会生成一个UIWindow来记录相关内容,包括实例化lua的UIBaseView的实例,持有者就是指定的layer,参数为界面lua路径,也包括VIEW_CONFIG配置等。打开界面的时候,会通过Addressable加载并实例化UI界面,然后调用View的Awake方法。最后就是激活窗口,把窗口在当前层级置顶,调用SetActive方法,调度窗口及Awake下添加组件的OnEnable方法。同理关闭界面的时候,传入lua路径,同样会调用SetActive方法,调度窗口及Awake下添加组件的OnDisable方法。

 

完整的UIManager.lua:

 

六、例子

 

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: