关于Lua的Unity UI面向过程编程模板

发表于2017-07-27
评论1 4.5k浏览

关于Lua的Unity UI面向过程编程模板

该模板基于xLua实现,对xLua不熟悉的可以去了解下。改用别的Lua热更方案也容易。

先发下示例地址

https://github.com/skylecn/xLua/tree/master/Assets/XLua/Examples/UIFrame

窗口如下

窗口左侧是一个列表,选择列表中的项,右边会显示当前选择项的内容。

下面是实现窗口功能的Lua文件。

require 'item'  --列表项
local ue = CS.UnityEngine
--窗口
Panel = {
	--Awake事件
	--data是一个table,其中包含该UI的gameObject和注册的UI组件,也可以增加自己的变量
	Awake = function (data)
		data.list = {};	--保存生成的Item的data
		local go = ue.Resources.Load('Item')
		for index=1,3 do
			local item = ue.Object.Instantiate(go)
			item.transform.parent = data.leftView.transform
			item.transform.localScale = ue.Vector3.one
			data.list[index] = item:GetComponent('FuncLuaBehavior').luaData
			Item.Init(data.list[index], data, index)
		end
	end;
	--选择某项
	SelectItem = function (data, num)
		for index= 1, #data.list do
			data.num:GetComponent('Text').text=num
			Item.SetLight(data.list[index], index==num and true or false)
		end
	end;
}

在以上文件中只定义了两个函数,数据data作为函数参数被处理,这就是面向过程的编程方式。那data具体是什么?又是如何被定义的呢?看下面的代码。

[LuaCallCSharp]
public class FuncLuaBehavior : MonoBehaviour {
    public string luaFile;
    public Injection[] injections;
    internal static LuaEnv luaEnv = new LuaEnv(); //all lua behaviour shared one luaenv only!
    LuaTable dataTable; // Lua table,包括C#创建的和Lua中创建的数据
    LuaTable funcTable; // Lua实现的事件响应函数和功能函数
    public LuaTable luaData
    {
        get { return dataTable; }
    }
    void Awake()
    {
        //加载Lua文件
        luaEnv.DoString(string.Format("require '{0}'", luaFile ));
        //定义dataTable
        dataTable = luaEnv.NewTable();
        //插入需要处理的UI组件到dataTable中
        dataTable.Set("gameObject", gameObject);
        foreach (var injection in injections)
        {
            dataTable.Set(injection.name, injection.value);
        }
        //获取Lua文件中函数table的引用
        funcTable = luaEnv.Global.Get(luaFile);
        if (funcTable != null)
        {
            var luaAwake = funcTable.Get<action>("Awake");
            if (luaAwake != null)
            {
                luaAwake(dataTable);
            }
        }
    }
}</action

上面代码部分借鉴了xLua中LuaBehaviour的实现,面向过程的支持主要是dataTable和funcTable。dataTable即该窗口的“数据”,在Awake中创建并插入需要处理的UI组件。funcTable引用在Lua文件定义的table,也就是我们先前的Lua文件。然后我们触发Lua中的Awake事件,事件的参数就是dataTable。

这就是整个模板的结构。

以下是该示例另一部分Lua文件,结合代码中的注释来理解整个实现。

local ue = CS.UnityEngine
--列表项
Item = {
	--Awake事件
	Awake = function (data)
		data.button:GetComponent("Button").onClick:AddListener(function()
			Panel.SelectItem(data.panel, data._num)
		end)
	end;
	--初始化
	Init = function (data, panel, num)
		data.panel = panel	--保存父窗口引用
		data._num = num --保存编号
		data.num:GetComponent("Text").text = num
	end;
	--设置选中状态
	SetLight = function (data, light)
		data.light:SetActive(light)
	end;
}

为什么不面向对象,而要面向过程?

  • 面向过程比面向对象简单清晰,容易上手,而UI功能也比较简单,就是事件响应,用面向过程就可以解决问题
  • Lua的面向对象基于metatable实现,写一个类声明就需要好多行代码,相比高级语言的class声明还复杂
  • Lua中定义的变量的作用域有全局和当前文件,但只能对应一个C#对象,如果C#的多个对象,就需要定义多个变量与之对应,实现背包这样的功能比较麻烦。使用面向过程,数据和功能分离,Lua中实现功能,数据由C#定义和管理。数据和UI组件的生命周期对应,Awake时定义,OnDestroy时销毁。数据作为参数递到Lua事件,在Lua事件响应中处理对应的UI组件。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引