lua类创建和继承的关键是metatable的使用,这里直接使用云风大大的代码(部分修改)
local _class={}
function class(super)
local class_type={}
class_type.ctor=false
class_type.super=super
class_type.new=function(...)
local obj={}
do
local create
create = function(c,...)
if c.super then
create(c.super,...)
end
if c.ctor then
c.ctor(obj,...)
end
end
create(class_type,...)
end
setmetatable(obj,{ __index=_class[class_type] })
return obj
end
local vtbl={}
_class[class_type]=vtbl
setmetatable(class_type,{__newindex=
function(t,k,v)
vtbl[k]=v
end
})
if super then
_class[super].base = _class[super];
setmetatable(vtbl,{__index=
function(t,k)
local ret=_class[super][k]
vtbl[k]=ret
return ret
end
})
end
return class_type
end
---------------------
--base_type=class() -- 定义一个基类 base_type
--function base_type:ctor(x) -- 定义 base_type 的构造函数
-- print("base_type ctor")
-- self.x=x
--end
--function base_type:print_x() -- 定义一个成员函数 base_type:print_x
-- print(self.x)
--end
--function base_type:hello() -- 定义另一个成员函数 base_type:hello
-- print("hello base_type")
--end
-------------------------------
--test=class(base_type) -- 定义一个类 test 继承于 base_type
--function test:ctor() -- 定义 test 的构造函数
-- print("test ctor")
--end
--function test:hello() -- 重写 base_type:hello 为 test:hello
-- test.base.hello(self);
-- print("hello test")
--end
---------------------------------------
--a=test.new(1) -- 输出两行,base_type ctor 和 test ctor 。这个对象被正确的构造了。
--a:print_x() -- 输出 1 ,这个是基类 base_type 中的成员函数。
--a:hello() -- 输出 hello test ,这个函数被重载了。
lua中的使用可以参考上面的注释代码,在c#中我们需要改下以前的luamono类,代码如下
using UnityEngine;
using LuaInterface;
public class LuaMono : MonoBehaviour
{
public string ModualName;
public LuaTable Table { get; private set; }
private bool m_isClass = false;
private LuaFunction m_awakeFunc;
private LuaFunction m_startFunc;
private LuaFunction m_enableFunc;
private LuaFunction m_disableFunc;
private LuaFunction m_destroyFunc;
private LuaFunction m_clickFunc;
private void Awake()
{
if (Table == null)
{
object[] objs = LuaManager.Instance.DoFile(ModualName);
Table = objs[0] as LuaTable;
if (Table == null)
{
Debug.LogError("cant find lua table");
}
}
GetFunction();
if (m_awakeFunc != null)
{
if (m_isClass)
{
m_awakeFunc.Call(Table, gameObject);
}
else
{
m_awakeFunc.Call(gameObject);
}
}
}
protected virtual void GetFunction()
{
m_awakeFunc = Table.GetLuaFunction("Awake");
m_startFunc = Table.GetLuaFunction("Start");
m_enableFunc = Table.GetLuaFunction("OnEnable");
m_disableFunc = Table.GetLuaFunction("OnDisable");
m_destroyFunc = Table.GetLuaFunction("OnDestroy");
m_clickFunc = Table.GetLuaFunction("OnClick");
}
private void Start()
{
if (m_startFunc != null)
{
if (m_isClass)
{
m_startFunc.Call(Table);
}
else
{
m_startFunc.Call();
}
}
}
private void OnEnable()
{
if (m_enableFunc != null)
{
if (m_isClass)
{
m_enableFunc.Call(Table);
}
else
{
m_enableFunc.Call();
}
}
}
private void OnDisable()
{
if (m_disableFunc != null)
{
if (m_isClass)
{
m_disableFunc.Call(Table);
}
else
{
m_disableFunc.Call();
}
}
}
private void OnClick()
{
if (m_clickFunc != null)
{
if (m_isClass)
{
m_clickFunc.Call(Table);
}
else
{
m_clickFunc.Call();
}
}
}
private void OnDestroy()
{
LuaUtils.ClearMemory();
if (m_destroyFunc != null)
{
if (m_isClass)
{
m_destroyFunc.Call(Table);
}
else
{
m_destroyFunc.Call();
}
}
}
private void Reset()
{
ModualName = gameObject.name;
}
public void SetTable(LuaTable lt)
{
Table = lt;
m_isClass = true;
}
}
使用方法和以前一样,不过在lua中实例化预制体后需要调用SetTable方法手动赋值。