項目後期Lua接入筆記08--Lua面向對象及LuaBehaviour的再設計

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章