[Unity + XLua]如何在LuaBehaviour组件上序列化Lua中声明的变量
本文使用了以下Github公开库:
Unity的序列化以及存储
-
当将继承自MonoBehaviour的C#脚本作为组件,Unity会自动将可序列化的属性显示在Inspector面板上,供开发者进行便携的设置,如下图
-
而当脚本组件在预制体(Prefab)上,则会将组件上的信息存储在预制体中,使用文本处理软件打开预制体就可以看到,如下图(上面的变量T)
XLua的引入
引入XLua后,我们可以通过在预制体上挂载LuaBehaviour组件,再将Lua脚本绑定到LuaBehaviour组件上,使得可以针对某一个游戏对象使用Lua控制,这一块可以参考XLua官方repo的教程。但是也有需要像Unity组件那样进行序列化设置初始值的时候,那么接下来就介绍方法。
思路:
-
使用XLua框架的
LuaTable、LuaFunction
和smilehao提供框架中的BaseClass实现 -
BaseClass用于继承一些函数,不至于每个脚本都写一些相同的逻辑
-
LuaTable
用于获取Lua脚本的函数、变量、变量类型等参数 -
通过LuaTable表中我们设置的变量名称以及变量类型,继承自
UnityEngine.Object
的类型如GameObject
、Transform
等就使用UnityEngine.Object
进行序列化,使用EditorGUILayout.ObjectField
进行绘制 -
而一些值类型如
int
,float
、Vector3
使用字符串进行序列化,但是使用的Unity提供的JsonUtility
进行序列化,保证稳定性(这个本文不会介绍,具体看本文开头的blueberryzzz的LuaBehaviour序列化)
脚本
LuaBehaivour.lua
- 新建LuaBehaviour.lua,使用BaseClass写一个LuaBehaivour类,而其他类继承自这个类后通过规定的函数(此处为
__Define
)进行变量与类的定义
local Class = require("Core.Class")
local LuaBehaviour = Class("LuaBehaviour")
local function CallDefine(classType, defineSelf)
if classType.super then
CallDefine(classType.super, defineSelf)
end
--- 派生类中定义变量与变量类型的函数
if classType.__Define then
classType.__Define(defineSelf)
end
end
local defineSelf = {
}
local defineStore = {
}
-- 保证C#端的LuaTable中变量顺序
setmetatable(defineSelf, {
__newindex = function(_ , n, t)
table.insert(defineStore, {
name = n, type= t})
end})
local function _ClearLocalDefineList()
for i = 1, #defineStore do
defineStore[i] = nil
end
end
function LuaBehaviour:Define()
--这个 define 可能会多次被调用。 只执行一次即可
if rawget(self, "_DefineList") ~= nil then return end
_ClearLocalDefineList()
self._DefineList = {
}
CallDefine(self, defineSelf)
for key, value in ipairs(defineStore) do
table.insert(self._DefineList, {
name = value.name, type = value.value})
end
end
return LuaBehaviour
- 在C#脚本中调用上述的
Define
函数,就会生产一个_DefineList
,这个_DefineList
中就存储了需要序列化的变量名称和变量类型,并且是按照自己写的顺