[专栏作家] Lua写UI的一些使用心得

Posted 游戏蛮牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[专栏作家] Lua写UI的一些使用心得相关的知识,希望对你有一定的参考价值。

之前提到,根据我们的项目需求,战斗部分,用c#来写。其他我们都用lua来写,保证在ios平台可热更新的部分更多。


lua在游戏中,很多时候,主要做的是UI部分。所以,我们今天只说说在UI上的一点小心得。我们使用的是UGUI,以下,均以UGUI来做说明。


在UI部分,除了具体的逻辑,开始很大一部分工作,是如何在代码中,获得我们需要的对应的各个Gameobject或者component。


我们先简单回顾以下,如果用C#来写UI逻辑,大体上有几种办法获得component:

  • 在代码中,通过路径读取。例如:

GetComponentByPath和GetComponentByName是我们简单扩展的方法

这种方法,最原始,麻烦之处就不用细说,都能理解。


2. 这种方法是将脚本挂在prefab上,直接拖对应的component到field上

[专栏作家] Lua写UI的一些使用心得

这种方式简单明了,但是我们如果用lua做,不可能给每个界面,额外加一个c#的类。


3. 有些项目会选择给prefab上的资源以一定的命名规则,然后写逻辑自动生成。

[专栏作家] Lua写UI的一些使用心得

根据命名前缀或者后缀来标记


这种办法好处是,写一个通用的解析代码,后面就省事了。坏处是,在prefab元素的命名上,限制有些多,如果需要更多一些的逻辑,string的描述能力是不足的。


4. 还有一种,类似3,给元素打上标记,然后离线自动生成读取的代码片段,类似很多的excel配表转数据class的处理方式。 这种方式和上面一种的问题类似。


以上是c#来写UI,常见的几种处理方式。肯定还有很多不同的方式,也许更优,我就不了解了,希望大家分享。


回到lua,我们用lua来做UI component引用的自动获得,以上4种办法,都有变种可以处理。最后,我们选择第二种方式来处理,在prefab上挂一个通用的c#脚本(此脚本仅做配置表述,变动很小,极少数不做热更新的之一。关于热更新c#脚本,参见之前文章。),然后将c#脚本配置的数据,运行时自动生成lua table的key,如果我们给一个table class化,其实也就像c#的属性了。

具体步骤如下:


  • 制作prefab,在prefab上挂一个FieldCfger的脚本

[专栏作家] Lua写UI的一些使用心得

[专栏作家] Lua写UI的一些使用心得

[专栏作家] Lua写UI的一些使用心得

[专栏作家] Lua写UI的一些使用心得

在prefab上挂脚本,存数据

[专栏作家] Lua写UI的一些使用心得

[专栏作家] Lua写UI的一些使用心得

[专栏作家] Lua写UI的一些使用心得

[专栏作家] Lua写UI的一些使用心得

[专栏作家] Lua写UI的一些使用心得

[专栏作家] Lua写UI的一些使用心得

Type:选择obj的类型,不同的类型,会有不同的处理

LuaType:我们会做一些自动的lua绑定,后续介绍。

Custom Name:如果不想用prefab上元素自身的名字,可以另外取名字,少数情况会用到。


2. 接下来,当我们打开一个UI界面的时候,会根据这个配置,初始化好table的数据,部分代码如下:


以上是示例代码,这样,我们在lua中,对一个属性的访问,就非常简单了:

[专栏作家] Lua写UI的一些使用心得

直接通过self.xxxx 来直接获取对应的component,并且可以self._go来获取gameobject,self._tf来获得transform,self.xxxx_go获得对应component的gameobject。


这里,完成了大部分元素的获取,做UI的时候,在fieldCfger脚本上拖拽上需要的元素,选择好type,在lua部分,就可以直接获取对应type的component了,省去了大部分烦杂的getComponent的脚本,工作效率和c#原生开发一样,不自动生成脚本,不需要对取名做特殊处理,还可以根据项目需求,修改这个脚本,增加更多对元素的描述和配置。


上面两步,已经可以解决大部分问题,但是,还有一些方面,我们做了一些加强,答案就在:

[专栏作家] Lua写UI的一些使用心得

当我们给元素选择类型是Gameobject的时候,会额有一个luaFieldType的选项,这里会额外做一些处理,主要是为了解决下面这个问题。


我们做UI的时候,经常需要分层处理逻辑或显示。例如,一个战斗UI界面,可能有攻击方头像区域,技能按钮区域,被攻击方或Boss的血条,连击数显示等等多个模块。我们肯定不希望所有逻辑写在一个类里面(lua实现的类),而是希望有个层级结构。所以,我们希望能得到table[key] = table,属性也是一个table。例如:


[专栏作家] Lua写UI的一些使用心得


一个UI的层级例子

那么,battleDlg是一个table,selfHeadCtrl,comboCtrl,inputCtrl也是一个table,每个子table,就有自己的属性。例如,我要访问操作按钮a,就用self.inputCtrl.btn_a就可以了,这是简单的将属性分层。也就是LuaFieldType中的Normal类型。对应prefab就如这样配置:


[专栏作家] Lua写UI的一些使用心得

这里指明按一层处理,即生成一个table


[专栏作家] Lua写UI的一些使用心得

下一层挂自己的元素


当然,还可以生成我们定义的,包含逻辑的一个table(lua class),这种一般用在我们需要对这个子模块,写模块内的逻辑。

[专栏作家] Lua写UI的一些使用心得

这里填一个自定义的table


[专栏作家] Lua写UI的一些使用心得

挂sell ctrl自己属性元素


[专栏作家] Lua写UI的一些使用心得


对应的lua table中,就可以直接获得属性

通过这种方式,很方便地就自动处理好对lua中各个component属性的赋值。

另外几种LuaFieldType,都是对这种使用方式的扩展。


还有一种需求,比如我们有个角色列表的UI,一次展示三个角色,我不希望在prefab上一次创建好三个角色信息子UI,而是在prefab里面,做一个模板,运行时去Instantiate三个子UI,这是常见的处理方式。


为了方便处理,我们可以在这个模板上挂FieldCfger,然后在运行时,Instantiate出这个模板,并自动绑定好对应的lua table, 如下:

[专栏作家] Lua写UI的一些使用心得

拥有逻辑的table


空table


对应打的工具方法

对lua这块的介绍,基本就到这里了,这个方法,能减少大量的低技术含量的工作量,并且在运行时使用也很方便。按照这个思路,也方便进行扩展,在非UI的逻辑下,也可以运用。目前用下来,非常方便,大大提高了开发的速度,让我们写lua,轻松了不少。


最后,lua的使用,必定没有c#写起来舒爽,但是当lua必不可少的情况下(个人觉得ILRuntime还不够成熟,我们稳妥为主,还是用lua),能让我们用起来更轻松点,也是值得项目努力的。


此方案还有不少可以优化之处,就不一一列举。这次就分享这个小的点吧,希望让一些还没用lua的项目,减少一些对lua的恐惧,其实,并没有那么难。

最后,说明一下:


我们的lua class,用的云风写的一个class,网上可以搜到。

在vscode 上的插件luaide,可以做到不错的代码提示,也可以断点debug,方便了我们的开发,值得推荐。


Gordon


以上是关于[专栏作家] Lua写UI的一些使用心得的主要内容,如果未能解决你的问题,请参考以下文章

lua+libuv的一些开发心得

lua+libuv的一些开发心得

[专栏作家] Lua中的消息分发实现

[专栏作家] 使用xlua读取lua数据表性能分析

Lua使用心得

Lua使用心得