SLua學習紀錄,自訂義的LuaBehavior

LuaBehavior 繼承 MonoBehaviour 在Lua裡面實作 Start Update等Function

LuaBehavior .cs

using SLua;
using System;
using System.Collections;
using System.IO;
using UnityEngine;

[CustomLuaClass]
public class LuaBehavior : MonoBehaviour
{
    LuaSvr svr;
    LuaTable self;

    [CustomLuaClass]
    public delegate void UpdateDelegate(object self);
    UpdateDelegate ud;

    [CustomLuaClass]
    public delegate void StartDelegate(object self);
    StartDelegate sd;

    [CustomLuaClass]
    public delegate void DestoryDelegate(object self);
    DestoryDelegate destoryDele;

    [SerializeField]
    string fileName;

    Action initCompleteAction;

    public virtual void Awake()
    {
        svr = new LuaSvr();

        svr.init(tick, InitComplete);

        LuaState.main.loaderDelegate += LuaLoader;
    }

    void tick(int p)
    {
        Debug.Log($"Lua init Progress {p}");
    }

    void InitComplete()
    {
        self = svr.start(fileName) as LuaTable;

        ud = functionCast<UpdateDelegate>("update");

        sd = functionCast<StartDelegate>("start");

        destoryDele = functionCast<DestoryDelegate>("destory");

        initComplete();
    }

    [DoNotToLua]
    public virtual void initComplete() { }

    [DoNotToLua]
    public byte[] LuaLoader(string fn, ref string absoluteFn)
    {
        if (string.IsNullOrEmpty(fn))
        {
            Debug.LogError($"Get Lua File Name is Empty");
            return new byte[] { };
        }

        string path = $"{Directory.GetCurrentDirectory()}/Assets/Script/Lua/{fn}.txt";
        return File.ReadAllBytes(path);
    }

    public virtual void Start()
    {
        StartCoroutine(waitStart());
    }

    IEnumerator waitStart()
    {
        while (sd == null)
            yield return null;

        sd(self);
    }

    void Update()
    {
        if (ud == null)
            return;

        ud(self);
    }

    private void OnDestroy()
    {
        if (destoryDele == null)
            return;

        destoryDele(self);
    }

    T functionCast<T>(string tableName) where T : class
    {
        LuaFunction luaFunction = (LuaFunction)self[tableName];

        if (luaFunction == null)
        {
            Debug.LogError($"Get {tableName} LuaFunction is null");
        }

        return luaFunction.cast<T>();
    }
}

Lua寫法   TestLua.txt

function main()
    print("lua--- run lua main function")
    
    class.testMain = GameObject.Find("Main"):GetComponent("MainTest")
  
    return class
end

-- 在C#的Update函数中被调用
function class:update()
    time = time + Time.deltaTime
end

function class:start()
    print("Start Run")
end

function class:destory()
    print("destory")
end

另外一種不使用委託寫法

LuaBehavior .cs 修改為

 public LuaFunction getLuaFunction(string key)
    {
        return svr.luaState.getFunction(key);
    }

    public virtual void Start()
    {
        StartCoroutine(waitStart());
    }

    IEnumerator waitStart()
    {
        while (self == null)
            yield return null;

        getLuaFunction("start").call();
    }

    void Update()
    {
        if (self == null)
            return;

        getLuaFunction("update").call();
    }

    private void OnDestroy()
    {
        if (self == null)
            return;

        getLuaFunction("destory").call();
    }

Lua修改寫法   TestLua.txt

-- 在C#的Update函数中被调用
function update()
    time = time + Time.deltaTime
end

function start()
    print("Start Run")
end

function destory()
    print("destory")
end

但不使用委託的方法下 依照slua GitHub裡面的說法 有可能會導致額外的box , unbox的gc alloc風險 

所以導出對應的delegate 並轉換成luafunction為對應的delegate 就可以避免gc alloc的開銷

補充:

[CustomLuaClass] 此特性可以修飾類別註冊到SLua執行環境中 如果沒有加上 要呼叫類別必須用字串方式呼叫

function main()
    print("lua--- run lua main function")
    
    class.testMain = GameObject.Find("Main"):GetComponent("MainTest")

    print("Print Log"..class.testMain == nill)
    return class
end

否則會報錯

有加上可以用以下方式呼叫

function main()
    print("lua--- run lua main function")
    
    class.testMain = GameObject.Find("Main"):GetComponent(MainTest)
    
    print("Print Log"..class.testMain == nill)
    return class
end