Tolua Examples 1 – 4 HelloWorld , Dofile & Require , CallLuaFunction , AccessingLuaVariables

Tolua Examples 1 – 4 HelloWorld  , Dofile & Require ,   CallLuaFunction  ,  AccessingLuaVariables

Examples:

 

1 HelloWorld

using UnityEngine;

using LuaInterface;

using System;

 

public class HelloWorld : MonoBehaviour

{

    void Awake()

    {

        LuaState lua = new LuaState();

        //lua_State 中放的是 lua 虛擬機器中的環境表、登錄檔、執行堆疊、虛擬機器的上下文等資料。

        //從一個主執行緒(特指 lua 虛擬機器中的執行緒,即 coroutine)中建立出來的新的 lua_State 會共享大部分資料,但會擁有一個獨立的執行堆疊。所以一個執行緒物件擁有一個lua_State。

        //Lua_State細節內容:

        //https://blog.csdn.net/chenjiayi_yun/article/details/24304607

 

 

        lua.Start();

        string hello =

            @”               

                print(‘hello tolua#’)                                 

            “;

       

        lua.DoString(hello, “HelloWorld.cs”);//載入並執行?

 

        lua.CheckTop();//銷燬前呼叫了CheckTop,用於檢測LUA棧中是否還有未執行的指令

 

        lua.Dispose();

        lua = null;

    }

}

 

2 Dofile & Require

 using UnityEngine;

using System.Collections;

using LuaInterface;

using System;

using System.IO;

 

//展示searchpath 使用,require 與 dofile 區別

public class ScriptsFromFile : MonoBehaviour

{

    LuaState lua = null;

    private string strLog = “”;   

 

    void Start ()

    {

#if UNITY_5 || UNITY_2017 || UNITY_2018    

        Application.logMessageReceived = Log;

#else

        Application.RegisterLogCallback(Log);

#endif        

        lua = new LuaState();                

        lua.Start();       

        //如果移動了ToLua目錄,自己手動修復吧,只是例子就不做配置了

        string fullPath = Application.dataPath “\\ToLua/Examples/02_ScriptsFromFile”;

        lua.AddSearchPath(fullPath);       

    }

 

    void Log(string msg, string stackTrace, LogType type)

    {

        strLog = msg;

        strLog = “\r\n”;

    }

 

    void OnGUI()

    {

        GUI.Label(new Rect(100, Screen.height / 2 – 100, 600, 400), strLog);//列印到GUI上

 

        if (GUI.Button(new Rect(50, 50, 120, 45), “DoFile”))

        {

            strLog = “”;

            lua.DoFile(“ScriptsFromFile.lua”);                       

        }

        else if (GUI.Button(new Rect(50, 150, 120, 45), “Require”))

        {

            strLog = “”;           

            lua.Require(“ScriptsFromFile”);

        }

 

        //          require:不需要字尾

        //          載入檔案並執行程式碼塊,對於相同的檔案只執行一次

        //          呼叫:require(“filename”)

 

        //          dofile:

        //          載入檔案並執行程式碼塊,對於相同的檔案每次都會執行

        //          呼叫:dofile(“filename”)

        //          錯誤處理:如果程式碼塊中有錯誤則會引發錯誤

        //          每次載入檔案時都會執行程式塊

 

        //Lua中require,dofile,loadfile,dostring,loadstring,loadlib,load之間的區別

        //https://www.cnblogs.com/heyongqi/p/5167088.html

 

 

        lua.Collect();

        lua.CheckTop();

    }

 

    void OnApplicationQuit()

    {

        lua.Dispose();

        lua = null;

#if UNITY_5 || UNITY_2017 || UNITY_2018

        Application.logMessageReceived -= Log;

#else

        Application.RegisterLogCallback(null);

#endif

    }

}

 

關於logMessageReceived:

https://docs.unity3d.com/ScriptReference/Application-logMessageReceived.html

只有接收到在主執行緒的日誌才會觸發

Application.logMessageReceivedThreaded是可以接收不是從主執行緒來的日誌也會觸發

 

3 CallLuaFunction

using UnityEngine;

using System.Collections;

using LuaInterface;

using System;

 

public class CallLuaFunction : MonoBehaviour

{

    private string script =

        @”  function luaFunc(num)                       

                return num 1

            end

 

            test = {}

            test.luaFunc = luaFunc

        “;

 

    LuaFunction luaFunc = null;

    LuaState lua = null;

    string tips = null;

   

    void Start ()

    {

#if UNITY_5 || UNITY_2017 || UNITY_2018

        Application.logMessageReceived = ShowTips;

#else

        Application.RegisterLogCallback(ShowTips);

#endif

        new LuaResLoader();

        lua = new LuaState();

        lua.Start();

        DelegateFactory.Init();       

        lua.DoString(script);

 

        //Get the function object

        luaFunc = lua.GetFunction(“test.luaFunc”);

 

        if (luaFunc != null)

        {

            int num = luaFunc.Invoke<int, int>(123456);//第一個是引數型別,第二個是返回值型別

            Debugger.Log(“generic call return: {0}”, num);

 

            num = CallFunc();

            Debugger.Log(“expansion call return: {0}”, num);

 

            Func<int, int> Func = luaFunc.ToDelegate<Func<int, int>>();//建立一個函式委託控制代碼

            num = Func(123456);

            Debugger.Log(“Delegate call return: {0}”, num);

           

            num = lua.Invoke<int, int>(“test.luaFunc”, 123456, true);//使用LUA虛擬機器物件裡的Invoke來實現呼叫

            //LuaState.Invoke 臨時呼叫一個lua function並返回一個值,這個操作並不快取lua function,適合頻率非常低的函式呼叫。

            Debugger.Log(“luastate call return: {0}”, num);

        }

 

        lua.CheckTop();

    }

 

    void ShowTips(string msg, string stackTrace, LogType type)

    {

        tips = msg;

        tips = “\r\n”;

    }

 

#if !TEST_GC

    void OnGUI()

    {

        GUI.Label(new Rect(Screen.width / 2 – 200, Screen.height / 2 – 150, 400, 300), tips);

    }

#endif

 

    void OnDestroy()

    {

        if (luaFunc != null)

        {

            luaFunc.Dispose();

            luaFunc = null;

        }

 

        lua.Dispose();

        lua = null;

 

#if UNITY_5 || UNITY_2017 || UNITY_2018

        Application.logMessageReceived -= ShowTips;

#else

        Application.RegisterLogCallback(null);

#endif

    }

 

    int CallFunc()//invoke是對這些的封裝

    {       

        luaFunc.BeginPCall();               

        luaFunc.Push(123456);//壓入函式呼叫需要的引數,通過眾多的過載函式來解決引數轉換gc問題

        luaFunc.PCall();        //裡面呼叫了luaState.PCall, pcall以一種”保護模式”來呼叫第一個引數,因此pcall可以捕獲函式執行中的任何錯誤。

        int num = (int)luaFunc.CheckNumber();//提取函式返回值, 並檢查返回值為lua number型別

        luaFunc.EndPCall();//釋放LuaFunction, 遞減引用計數,如果引用計數為0, 則從_R表刪除該函式

        return num;               

    }

}

 

4  AccessingLuaVariables

using UnityEngine;

using System.Collections.Generic;

using LuaInterface;

 

public class AccessingLuaVariables : MonoBehaviour

{

    private string script =

        @”

            print(‘Objs2Spawn is: ‘..Objs2Spawn)

            var2read = 42

            varTable = {1,2,3,4,5}

            varTable[15] = 25

            varTable[25] = 35

            varTable.default = 1

            varTable.map = {}

            varTable.map.name = ‘map’

           

            meta = {name = ‘meta’}

            setmetatable(varTable, meta)

           

            function TestFunc(strs)

                print(‘get func by variable’)

            end

        “;

 

    void Start ()

    {

#if UNITY_5 || UNITY_2017 || UNITY_2018

        Application.logMessageReceived = ShowTips;

#else

        Application.RegisterLogCallback(ShowTips);

#endif

        new LuaResLoader();

        LuaState lua = new LuaState();

        lua.Start();

        lua[“Objs2Spawn”] = 5;//設定全域性變數,實現:LuaState通過實現public object this[string fullPath]{ … set{ … 來實現的

        lua.DoString(script);

 

        //通過LuaState訪問

        Debugger.Log(“Read var from lua: {0}”, lua[“var2read”]);

        Debugger.Log(“Read table var from lua: {0}”, lua[“varTable.default”]);  //LuaState 拆串式table

 

        LuaFunction func = lua[“TestFunc”] as LuaFunction;

        func.Call();

        func.Dispose();

 

        //cache成LuaTable進行訪問

        LuaTable table = lua.GetTable(“varTable”);

        Debugger.Log(“Read varTable from lua, default: {0} name: {1}”, table[“default”], table[“map.name”]);

        table[“map.name”] = “new”;  //table 字串只能是key

        //LuaState.GetTable 從lua中獲取一個lua table, 可以串式訪問比如lua.GetTable(“varTable.map.name”) 等於 varTable->map->name

        //LuaTable 支援this操作符,但此this不支援串式訪問。比如table[“map.name”] “map.name” 只是一個key,不是table->map->name

 

        Debugger.Log(“Modify varTable name: {0}”, table[“map.name”]);

 

        table.AddTable(“newmap”);

        LuaTable table1 = (LuaTable)table[“newmap”];

        table1[“name”] = “table1”;

        Debugger.Log(“varTable.newmap name: {0}”, table1[“name”]);

        table1.Dispose();

 

        table1 = table.GetMetaTable();

 

        if (table1 != null)

        {

            Debugger.Log(“varTable metatable name: {0}”, table1[“name”]);

        }

 

        object[] list = table.ToArray();//連續下標的物件會被存進來,比如下標15和25那兩個就不會

 

        for (int i = 0; i < list.Length; i )

        {

            Debugger.Log(“varTable[{0}], is {1}”, i, list[i]);

        }

 

        table.Dispose();          //luatable一定要釋放             

        lua.CheckTop();

        lua.Dispose();

    }

 

    private void OnApplicationQuit()

    {

#if UNITY_5 || UNITY_2017 || UNITY_2018

        Application.logMessageReceived -= ShowTips;

#else

        Application.RegisterLogCallback(null);

#endif

    }

 

    string tips = null;

 

    void ShowTips(string msg, string stackTrace, LogType type)

    {

        tips = msg;

        tips = “\r\n”;

    }

 

    void OnGUI()

    {

        GUI.Label(new Rect(Screen.width / 2 – 300, Screen.height / 2 – 200, 600, 400), tips);

    }

}