Unity+toLua+FairyGUI工程的lua业务层使用UI的方法

在lua层使用FairyGUI编辑器导出的UI实现业务逻辑

前言

本人目前进行中的项目,是基于Unity3d引擎进行开发,使用toLua框架将业务层转嫁到lua层面,方便进行热更新,UI方面使用FairyGUI编辑器。
对于如何配置tolua和fairygui环境在此不多赘述。本文主要思考在lua层如何去更好的编写UI相关的业务逻辑,因为在业务开发中,很多时候我们需要把UI中的view或者component做为看做某种特殊的对象(比如背包中的道具或者是角色血条信息栏之类的),为此需要给它扩展相关的变量和方法。本人在此抛砖引玉,提供一些思路,供于参考和讨论。

一、官方提供的扩展FairyGUI类的方法:fgui.extension_class(“FairyGUI类名”)

在FairyGUI的官方教程中,提供了这种方法用于扩展,复制一下官网的例子:

--定义扩展类。注意基础类型,不要搞错。例如按钮是GButton,一般的组件则是GComponent。
MyButton = fgui.extension_class(GButton)

--注意这里不是构造函数,是当组件已经构建完毕后调用的

function MyButton:ctor()
	print(self:GetChild('n1'))
end

--添加自定义的方法和字段
function MyButton:Test()
	print('test')
end

local get = tolua.initget(MyButton)
local set = tolua.initset(MyButton)
get.myProp = function(self)
	return self._myProp
end

set.myProp = function(self, value)
	self._myProp = value
	self:GetChild('n1').text = value
end

--注册扩展类。要在创建任何对象前注册好。
fgui.register_extension("ui://包名/我的按钮", MyButton)

--完成以上两步后,任何“我的按钮”这个资源创建出来的对象都可以使用MyButton访问了。例如:
local myButton = someComponent:GetChild("myButton") --这个myButton的资源是“我的按钮”
myButton:Test()
myButton.myProp = 'hello'

local myButton2 = UIPackage.CreateObject("包名","我的按钮")
myButton2:Test()
myButton2.myProp = 'world'

这种方法十分直接了当,扩展类与UI组件一一对应,在简单的开发中基本上大家使用这种方式即可满足需求。
但是本人在使用这种方式的过程中遇到了一些问题:

1、通用组件在不同页面需要不同的方法

这个问题怎么说呢,其实也不是一定非得在代码中去解决(在编辑UI的时候避免通用组件产生不同用法也可,但是咱没办法保证制作UI的同事能够理解这一层),但是既然遇到了或者说避免不了,那还是得解决一下。如果使用fgui.extension_class,那就两种办法:一是把所有可能的方法写到一个扩展类中(会使类特别庞大);二是实现多个扩展类,在不同的地方注册不同的类来创建对象(但是无法解决同一个页面同样的两个组件有不同的用法,Emmmm虽然这种情况听起来就很坑爹,但是还是那句话,咱没法保证╮(╯▽╰)╭)。

2、不同的组件表达同样的功能

这个问题主要是针对一些功能性组件,UI的同学需要有一些变化,所以他们制作成了不同的组件,但其实可能对我们来说这些组件在功能上基本没有区别,所以我们可能写了数个扩展类(扩展GButton的,扩展GComponent的等等),代码却几乎一样。

基于遇到的问题,在和同事沟通过之后,我们选取了下面这种方法来做扩展

二、自己编写lua的class(本质其实还是table)然后将UI对象做为变量赋值到class中

这种方法其实很好理解,举个例子:

local myComponent = class("myComponent")
function myComponent:ctor(uiComponent)
	self.ui = uiComponent
end

function myComponent:getChildAt(index)
	if self.ui then  --防报错判断
		return self.ui:GetChildAt(index)
	end
end

function myComponent:myFunction()
	print("myFunction")
end

return myComponent

这样就实现了一个自己的lua类,在使用的过程中,首先获取编辑器中的UI对象,然后new一个自己的lua类,将UI对象作为参数传进去,后面就可以使用自己的lua类对象来进行方法的调用了

local ui = view:GetChild("component")
local myui = myComponent.new(ui)
myui:myFunction()

这种扩展方式,将业务逻辑写在lua类中,然后在业务层与UI对象组合在一起进行使用,可以解决很多遇到的问题,类与类直接也可以建立比较明朗的继承关系。当然,也有它的缺点,比如与UI太过分离,使用中需要判断是否已经获得了实际的UI对象等等。但是就本人实际使用下来,觉得各方面还是不错的,不管是可读性还是使用,也不需要担心单组件多用,或者多组件同用。
如果大家是自己使用编辑器制作UI,可以将UI要使用的lua类路径,写在UI的自定义数据(userData)中,这样可以使用

require(ui.userData).new(ui)

的方式来创建,当使用不同的类的时候,只需要在编辑器修改userData即可。

尾声

到此,lua层使用fairygui的方法就介绍完毕,借此抛转引玉,如果大家有其他更好的使用方式,希望不吝交流指导,感谢!

你可能感兴趣的:(Unity+toLua+FairyGUI工程的lua业务层使用UI的方法)