项目后期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方法手动赋值。

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