ToLua的案例学习笔记

文章目录

  • 案例一:DoString的使用
  • 案例二:展示searchpath 使用,require 与 dofile 区别
  • 案例三:CS调用lua方法
  • 案例四:读写lua的全局变量的两种方式

复习lua与C#调用做的笔记,注释大部分都写在了代码里面

案例一:DoString的使用

using UnityEngine;
using LuaInterface;
using System;

public class HelloWorld : MonoBehaviour
{
    void Awake()
    {
        LuaState lua = new LuaState();//lua虚拟机
        lua.Start();//启动
        //lua代码
        string hello =
            @"                
                print('hello tolua#')                                  
            ";
        
        lua.DoString(hello, "HelloWorld.cs");//注解(1)
        lua.CheckTop();//检测堆栈是否平衡,每次都需要手动调用
        lua.Dispose();注解(2)
        lua = null;
    }
}

注解(1)
DoString()函数:执行字符串
注解(2)
lua.CheckTop();
检测堆栈平衡

案例二:展示searchpath 使用,require 与 dofile 区别

public class ScriptsFromFile : MonoBehaviour 
{
    LuaState lua = null;//lua虚拟机
    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文件路径
        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);

        if (GUI.Button(new Rect(50, 50, 120, 45), "DoFile"))
        {
            strLog = "";
            lua.DoFile("ScriptsFromFile.lua");       //DoFile                 
        }
        else if (GUI.Button(new Rect(50, 150, 120, 45), "Require"))
        {
            strLog = "";            
            lua.Require("ScriptsFromFile");            //require
        }

        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 
    }
}

lua代码:(ScriptsFromFile)
print("This is a script from a utf8 file")
print("tolua: 你好! こんにちは! 안녕하세요!")

DoFile和Require的区别
(1):经过运行发现每次调用DoFile都会输出,但是Require只会在第一次调用的时候输出。由此说明:DoFile在每次调用的时候都会对lua代码进行重新的加载。查看源码也是如此:
ToLua的案例学习笔记_第1张图片
但是Reuire是在执行的时候先检测模块是否存在,如果不存在则加载,存在直接return,源码奉上:
ToLua的案例学习笔记_第2张图片
(2)DoFile的参数需要带上.lua后缀,Require不需要后缀,直接名字就可。

案例三:CS调用lua方法

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();//注解(1)
        lua = new LuaState();//定义虚拟机
        lua.Start();//开启虚拟机
        DelegateFactory.Init();  //注解(2)      
        lua.DoString(script);

        //Get the function object
        luaFunc = lua.GetFunction("test.luaFunc");//加载test表中的luaFunc

        if (luaFunc != null)
        {
            int num = luaFunc.Invoke(123456);//注解(3)
            Debugger.Log("generic call return: {0}", num);

            luaFunc.BeginPCall();                
            luaFunc.Push(123456);
            luaFunc.PCall();        
            num = (int)luaFunc.CheckNumber();
            luaFunc.EndPCall();
            Debugger.Log("expansion call return: {0}", num);//注解(4)

            Func Func = luaFunc.ToDelegate>();//注解(5)
            num = Func(123456);
            Debugger.Log("Delegate call return: {0}", num);
            
            num = lua.Invoke("test.luaFunc", 123456, true);//注解6
            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
    }
}

注解(1):new LuaResLoader();
自定义加载lua文件,优先读取persistentDataPath/系统/Lua 目录下的文件(默认下载目录)未找到文件怎读取 Resources/Lua 目录下文件(仍没有使用LuaFileUtil读取),如果不想自定义则直接new LuaResLoader。自定义可参考:自定义加载lua文件,后面也会提到。
注解(2):DelegateFactory.Init();
目前没有很好的理解,大佬们有什么高招吗?
注解(3):int num = luaFunc.Invoke(123456)
通用的方式(有GC、慎用)
ToLua的案例学习笔记_第3张图片
注解(4):注释3的另一种形式(个人理解),只是对返回值进行了特殊处理。无GC,注意最后的dispose,否则造成内存泄漏。
注释(5):自行理解吧。
ToLua的案例学习笔记_第4张图片

注解(6):调用LuaState里面的函数
ToLua的案例学习笔记_第5张图片

案例四:读写lua的全局变量的两种方式

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.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();//默认加载lua
        LuaState lua = new LuaState();//虚拟机
        lua.Start();//启动
        lua["Objs2Spawn"] = 5;//相当于在lua文件中加入【Objs2Spawn = 5】即新增一个全局变量
        lua.DoString(script);//略

        //通过LuaState访问
        Debugger.Log("Read var from lua: {0}", lua["var2read"]); //读取第10行的变量,看第十行
        Debugger.Log("Read table var from lua: {0}", lua["varTable.default"]);  //LuaState 拆串式table,12行

        LuaFunction func = lua["TestFunc"] as LuaFunction;//TestFunc方法
        func.Call();//案例3的第一种方式,注意有GC,少量call可使用
        func.Dispose();

        //cache成LuaTable进行访问,很好理解
        LuaTable table = lua.GetTable("varTable");//包装成LuaTable
        Debugger.Log("Read varTable from lua, default: {0} name: {1}", table["default"], table["map.name"]);
        table["map.name"] = "new";  //table 字符串只能是key
        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();

        for (int i = 0; i < list.Length; i++)
        {
            Debugger.Log("varTable[{0}], is {1}", i, list[i]);
        }

        table.Dispose();                        
        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);
    }
}

你可能感兴趣的:(ToLua的案例学习笔记)