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方法手動賦值。