Unity--C# 调用LUA文件

C# 调用LUA文件

1.初始化Lua环境

XLua是一个为Unity设计的Lua编程语言解决方案,允许开发者在Unity项目中运行Lua脚本。

  1. 初始化Lua环境 :在Start方法中,创建了一个LuaEnv对象,这是XLua库中用于表示Lua执行环境的类。
  2. 执行Lua代码 :使用DoString方法执行一段Lua代码,这里是一个简单的打印语句print('hello xLua')
  3. 加载Lua脚本 :通过DoString方法使用require关键字加载了一个名为Main的Lua脚本。这个脚本应该位于Unity项目的Resources文件夹中,并且文件名需要以.txt结尾。
  4. 垃圾回收luaEnv.Tick()方法用于执行Lua环境的垃圾回收,帮助清理Lua中未手动释放的对象。这可以在帧更新中定时调用,或者在切换场景时调用。
  5. 销毁Lua环境luaEnv.Dispose()方法用于销毁Lua环境。在一般情况下,开发者可能不会销毁Lua环境,除非有特定的需求。
  6. 注意事项:在使用XLua时,需要注意资源的管理和加载路径,确保Lua脚本能够正确加载和执行。

具体代码如下

LuaEnv.cs

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using XLua;
using UnityEngine;

public class LuaEnv : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        // Lua 环境, 就是一个类
        LuaEnv luaEnv = new LuaEnv();
        // 执行Lua语言
        luaEnv.DoString("print('hello xLua')");
        // 输出: LUA: hello xLua

        // 执行lua脚本--使用require关键字, 同时, 默认实在Resources文件下的并且需要加上.txt后缀才能执行
        luaEnv.DoString("require('Main')");

        //帮助我们清楚Lua中我们没有手动释放的对象 垃圾回收
        //帧更新中定时执行 或者 切场景时执行
        luaEnv.Tick();

        // 销毁lua环境/解析器  一般不销毁
        luaEnv.Dispose();
    }
}

2.使用xluaLoader调用lua文件

通过AddLoader方法, 添加我们中定义的加载函数, 如果自定函数能后找到我们的lua文件, 他就不会去目录中找lua文件了.

  1. 自定义Lua脚本加载器 :通过AddLoader方法,将自定义的加载函数MyCustomLoader添加到Lua环境中。这个函数会在Lua执行require语句时被调用。
  2. 自定义加载逻辑MyCustomLoader函数接收一个文件路径参数。函数首先输出文件路径,然后构造一个完整的Lua文件路径。如果文件存在,使用File.ReadAllBytes读取文件内容并返回;如果文件不存在,输出错误信息。
  3. 加载Lua脚本 :通过DoString方法执行require('Main'),这会触发MyCustomLoader函数,根据自定义的路径加载名为Main的Lua脚本。

以下是LuaLoader.cs代码

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using XLua;
using UnityEngine;
using System.IO;

public class LuaLoader : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaEnv luaEnv = new LuaEnv();

        luaEnv.DoString("print('Hello World')");

        //xlua提供的一个路径重定向 的方法
        //允许我们自定义 加载 Lua文件的规则
        //当我们执行Lua语言 require 时 相当于执行一个1ua脚本
        //它就会 执行 我们自定义传入的这个函数

        luaEnv.AddLoader(MyCustomLoader);
        // 将MyCustomLoader的函数添加到了lua内部的一个委托中, 一旦找到了MyCustomLoader中的文件, 就不会执行其他的函数了
        // 最终是在AB中进行加载
        luaEnv.DoString("require('Main')");

    }

    public byte[] MyCustomLoader(ref string filepath)
    {
        // 文件名称
        Debug.Log(filepath);
        // 路径
        string luaFilePath = Application.dataPath + "/Lua/" + filepath + ".lua";
        Debug.Log("当前lua文件路径" + luaFilePath);

        // 判断文件是否存在
        if(File.Exists(luaFilePath))
        {
            return File.ReadAllBytes(luaFilePath);
        }
        else
        {
            Debug.Log("重定向文件错误, 错误文件名称: " + luaFilePath);
        }

        return null;
    }
}

3.LuaManager

在项目中, 我们是将lua脚本打包到ab包中, 然后进行加兹安lua脚本, 为了方便加载lua脚本,以及初始化lua环境, 因此, 可以使用管理器,以下是LuaManager.cs代码

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using XLua;
using UnityEngine;
using System.IO;

// lua 解析器的管理器
public class LuaManager : BaseManager<LuaManager>
{
    // 执行lua语言的函数
    // 释放垃圾
    // 销毁lua解析器
    // lua脚本重定向

    private LuaEnv luaEnv;

    #region 初始化lua解析器和重定向lua文件
    /// <summary>
    /// 初始化lua解析器
    /// </summary>
    public void Init()
    {
        if (luaEnv != null)
        {
            return;
        }
        luaEnv = new LuaEnv();

        // 加载lua脚本重定向
        luaEnv.AddLoader(MyCustomLoader);
        // 手动加载ab包读取lua文件
        // luaEnv.AddLoader(MyCustomABLoader);
        // 使用AB包管理器加载lua文件
        //luaEnv.AddLoader(MyCustomABPLoader);
    }

    /// <summary>
    /// 传入lua文名, 即可执行lua文件
    /// </summary>
    /// <param name="fileName"></param>
    public void DoLuaFile(string fileName)
    {
        string str = string.Format("require('{0}')", fileName);
        DoString(str);
    }

    /// <summary>
    /// 返回luaEnv中的_G表
    /// </summary>
    public LuaTable Global 
    {
        get 
        {
            return luaEnv.Global;
        }
    }

    /// <summary>
    /// 重定向lua脚本
    /// </summary>
    /// <param name="filepath"></param>
    /// <returns></returns>
    public byte[] MyCustomLoader(ref string filepath)
    {
        
        // 路径
        string luaFilePath = Application.dataPath + "/Lua/" + filepath + ".lua";
        Debug.Log("当前lua文件路径" + luaFilePath);

        // 判断文件是否存在
        if (File.Exists(luaFilePath))
        {
            return File.ReadAllBytes(luaFilePath);
        }
        else
        {
            Debug.Log("重定向文件错误, 错误文件名称: " + luaFilePath);
        }

        return null;
    }

    #endregion

    #region lua加载AB包文件

    // Lua脚本都会放在AB里
    // 最终通过加载AB包, 然后加载AB包中的lua脚本, 最后才是执行lua脚本
    // 重定向加载AB包中的lua脚本
    public byte[] MyCustomABLoader(ref string filepath)
    {
        // 1. 加载AB包 -lua包里面(这里有没有依赖包和依赖关系)
        string abPath = Application.streamingAssetsPath + "/PC" + "/lua.ab";
        // 因为lua的loader是需要理科返回资源, 因此加载lua的时候后就不要使用异步加载了, 使用同步加载
        AssetBundle ab = AssetBundle.LoadFromFile(abPath);
        Debug.Log("ab包加载lua脚本");

        // 2. 加载AB包中的lua文件
        TextAsset tx = ab.LoadAsset<TextAsset>(filepath + ".lua");
        // 3. 执行lua脚本
        return tx.bytes;
    }

    public byte[] MyCustomABPLoader(ref string filepath)
    {
        // 1. 加载AB包 -lua包里面(这里有没有依赖包和依赖关系)
        // 这里的报名需要和ABManager中的定义的路径相关-注意修改
        string abPath = "/lua.ab";
        // 因为lua的loader是需要理科返回资源, 因此加载lua的时候后就不要使用异步加载了, 使用同步加载
        Debug.Log("ab包管理器加载lua脚本");
        Debug.Log(filepath + ".lua");

        // 2. 加载AB包中的lua文件
        TextAsset tx = ABManager.GetInstance().LoadResources<TextAsset>(abPath, filepath + ".lua");

        // 3. 执行lua脚本
        return tx.bytes;
    }


    #endregion

    #region lua自带函数: 执行lua, 垃圾回收, 销毁lua解析器

    /// <summary>
    ///  执行lua语言
    /// </summary>
    /// <param name="str"></param>
    public void DoString(string str)
    {
        if(luaEnv == null)
        {
            Debug.Log("Lua解析器为空, 需要先初始化lua解析器");
            return;
        }
        luaEnv.DoString(str);
    }

    /// <summary>
    /// 释放垃圾, 每一帧都执行
    /// </summary>
    public void Tick()
    {
        if (luaEnv == null)
        {
            Debug.Log("Lua解析器为空, 无法进行垃圾回收");
            return;
        }
        luaEnv.Tick();
    }

    /// <summary>
    /// 销毁lua解析器
    /// </summary>
    public void Dispose()
    {
        if (luaEnv == null)
        {
            Debug.Log("Lua解析器为空, 无法销毁lua解析器");
            return;
        }
        luaEnv.Dispose();
        luaEnv = null;
    }
    #endregion
}

测试代码如下

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestLuaManager : MonoBehaviour
{
    LuaManager luaManager;
    void Start()
    {
        luaManager = LuaManager.GetInstance();
        luaManager.Init();
        //luaManager.DoString("require('Main')");
        luaManager.DoLuaFile("Main");
    }
}

4.C#调用Lua中的全局变量

在C#中调用lua中的变量只能是全局变量, 且C#中的变量的名称需要和Lua中的一致, 且修饰符为public, 因为protected和private的权限导致无法完成C#和lua的映射.

以下是lua脚本代码

Main.lua代码中引入了TestLua脚本

lua 复制代码
print("Lua Main 主入口")
-- 调用TestLua.lua脚本
require("TestLua")

TestLua.lua脚本如下

lua 复制代码
print("Test.lua")
intNumber = 1
floatNumber = 1.2
bool = true
str = "abc"

-- 无法通过c#的Gloabl获取lua中的局部变量
local x = 1
csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CallLuaVariable : MonoBehaviour
{
    LuaManager luaManager;
    void Start()
    {
        luaManager = LuaManager.GetInstance();
        luaManager.Init();
        luaManager.DoLuaFile("Main");
        int i = luaManager.Global.Get<int>("intNumber");

        // C# 修改lua的值
        luaManager.Global.Set("floatNumber", 23.45);
        float j = luaManager.Global.Get<float>("floatNumber");

        string k = luaManager.Global.Get<string>("str");
        bool l = luaManager.Global.Get<bool>("bool");

        Debug.Log("C# call lua variable - int = " + i);
        Debug.Log("C# call lua variable - float = " + j);
        Debug.Log("C# call lua variable - sting = " + k);
        Debug.Log("C# call lua variable - bool = " + l);
    }

}

5.C#调用Lua中的函数

函数的分类和调用方式

1.类型:无参无返回值

调用方式--使用委托

  1. UnityAction Unity自带的的不带参数的和返回值的委托
  2. C#自带的Action无参数无返回值的委托, 需要引入系统的命名空间
  3. 自定义的无参数无返回值的委托
  4. lua中的LuaFunction, 使用的时候使用.Call()的方式调用

lua中的脚本

csharp 复制代码
-- 无参无返回值
function test()
	print("无参数-无返回值函数")
end
csharp 复制代码
using System;
using UnityEngine;
using UnityEngine.Events;
using XLua;

// 委托: 无参-无返回值
public delegate void CallFunction();

/// <summary>
/// C# 调用lua中的全局函数
/// </summary>
public class CallLuaFunction : MonoBehaviour
{
    LuaManager luaManager;
    CallFunction cf;
    CallFunction2 cf2;
    void Start()
    {
        luaManager = LuaManager.GetInstance();
        luaManager.Init();
        luaManager.DoLuaFile("Main");

        #region 4种无参无返回值c#调用lua的方法

        // 将lua中的无参无返回值的函数添加到委托中
        cf = luaManager.Global.Get<CallFunction>("test");
        // 执行委托
        cf();

        // Unity自带的委托

        UnityAction ua = luaManager.Global.Get<UnityAction>("test");
        ua();

        // C#System中的委托
        Action ac = luaManager.Global.Get<Action>("test");
        ac();

        // X1ua提供的一种 获取函数的方式 少用 LuaFunction
        LuaFunction lf = luaManager.Global.Get<LuaFunction>("test");
        lf.Call();
        #endregion

    }
}
     

2.类型: 有参数有返回值

自定义的委托需要点击编辑器上的按钮生成代码才可以被注册

委托: 有参-有返回值

调用方式--使用委托

  1. 使用自定义含有参数含有返回值的委托
  2. 使用C#中自带的Func的委托, 该委托有17个重载, 可以灵活使用
  3. 使用xlua中的委托LuaFunction, 调用的时候, 使用.Call()进行调用, 返回值是一个列表/数组, 使用.Call()[下标]的方式得到返回值

lua中的脚本

csharp 复制代码
-- 有参有返回值
function test1(a)
	print("有参数-有返回值函数" .. a+1)
	return a + 1
end
csharp 复制代码
using System;
using UnityEngine;
using UnityEngine.Events;
using XLua;

// 自定义的委托需要点击编辑器上的按钮生成代码才可以被注册
// 委托: 有参-有返回值
[XLua.CSharpCallLua]
public delegate int CallFunction2(int arg);

public class CallLuaFunction : MonoBehaviour
{
    void Start()
    {
        // 自定义委托-- 需要在xlua中注册--编辑器中点击生成代码
        cf2 = luaManager.Global.Get<CallFunction2>("test1");
        int index = 100;
        Debug.Log(cf2(index));

        // 使用C#的有参有返回值的委托Func, 其中func中最多支持17个参数的委托
        // public delegate TResult Func<in T, out TResult>(T arg); out修饰的TResult是传出参数
        Func<int,int> func = luaManager.Global.Get<Func<int, int>>("test1");
        Debug.Log(func(200));

        // 使用LuaFunction进行有参有返回值的调用, 返回的是一个objec数组
        LuaFunction lf2 = luaManager.Global.Get<LuaFunction>("test1");
        Debug.Log(lf2.Call(300)[0]);
        
    }
}

3.类型: 有多个返回值

自定义的委托需要点击编辑器上的按钮生成代码才可以被注册

委托: 有参--有多个返回值

调用方式--使用委托

  1. 使用自定义含有参数含有返回值的委托
  2. 使用out或者ref来接收, 这需要看你的lua脚本中写的返回值的个数 和 类型
  3. 使用xlua中的委托LuaFunction, 调用的时候, 使用.Call()进行调用, 返回值是一个列表/数组, 使用.Call()[下标]的方式得到返回值

lua中的脚本

lua 复制代码
-- 有参多返回值
function test2( a )
	print("有参多返回值 " .. a)
	return 100,false,23.4,"China",a
end

CallLuaFunction.cs脚本代码如下

csharp 复制代码
using System;
using UnityEngine;
using UnityEngine.Events;
using XLua;

[XLua.CSharpCallLua]
public delegate int CallFunction3(int arg1, out bool arg2, out float arg3, out string arg4, out int arg5);
[XLua.CSharpCallLua]
public delegate int CallFunction4(int arg1, ref bool arg2, ref float arg3, ref string arg4, ref int arg5);

public class CallLuaFunction : MonoBehaviour
{
    void Start()
    {
        // 自定义委托进行多个值
        // 使用out和ref来接收, 这需要看你的lua脚本中写的返回值的个数 和 类型

        // public delegate int CallFunction3(int arg1, out bool arg2, out float arg3, out string arg4, out int arg5 );
        // 第一个返回int是委托的返回值写了. arg1是传入参数, arg2~arg4是传出参数
        // 这里需要区分变长参数

        // 使用out的情况
        bool a;
        float b;
        string c;
        int d;
        CallFunction3 cf3 = luaManager.Global.Get<CallFunction3>("test2");
        Debug.Log("多个返回值函数调用,使用out的方式,默认返回值:" + cf3(400, out a, out b, out c, out d));
        Debug.Log("返回值如下");
        Debug.Log("多个返回值: " + a);
        Debug.Log("多个返回值: " + b);
        Debug.Log("多个返回值: " + c);
        Debug.Log("多个返回值: " + d);
        
        Debug.Log("-----------------------------------");

        // 使用ref的情况, 需要初始化
        bool a2 = true;
        float b2 = 0.0f;
        string c2 = "";
        int d2 = -1;
        CallFunction4 cf4 = luaManager.Global.Get<CallFunction4>("test2");
        Debug.Log("多个返回值函数调用,使用ref的方式 默认返回值:" + cf4(600, ref a2, ref b2, ref c2, ref d2));
        Debug.Log("返回值如下");
        Debug.Log("多个返回值: " + a2);
        Debug.Log("多个返回值: " + b2);
        Debug.Log("多个返回值: " + c2);
        Debug.Log("多个返回值: " + d2);
        Debug.Log("---------------------------------");

        // 使用LuaFunction的方式
        LuaFunction lf3 = luaManager.Global.Get<LuaFunction>("test2");
        object[] objs = lf3.Call(700);
        for (int i = 0; i < objs.Length; i++)
        {
            Debug.Log("LuaFuncton返回多个值: " + objs[i].ToString());
        }
    }
}

4.类型: 变长参数

自定义的委托需要点击编辑器上的按钮生成代码才可以被注册

委托: 有参--有多个返回值

调用方式--使用委托

  1. 使用自定义含有返回值,只有C#总的params进行变长参数, 如果如果知道是什么类型就用什么类型接收
  2. 使用xlua中的委托LuaFunction, 调用的时候, 使用.Call()进行调用, 返回值是一个列表/数组, 使用.Call()[下标]的方式得到返回值

lua中的代码如下:

lua 复制代码
-- 有参变长参数
function test3( a, ... )
	print("有参-变长" .. a)
	-- 保存变长参数
	arg = {...}
	for k,v in pairs(arg) do
		 print("key:" .. k .."  " .. "value: " .. tostring(v))
	end
end

CallLuaFunction.cs脚本代码如下:

csharp 复制代码
using System;
using UnityEngine;
using UnityEngine.Events;
using XLua;

public delegate int CallFunction5(int arg1, params object[] args); //变长参数的类型 根据实际情况来定,最保险的就直接objct

public class CallLuaFunction : MonoBehaviour
{
    void Start()
    {
        // 使用C#自带的变长参数params, 需要根据lua中的函数变长参数的类型来确定.
        // 如果不确定的话, 可以直接使用object[], 这就涉及到了装箱拆箱的问题
        Debug.Log("使用C#的变长参数params进行调用lua变长参数的函数");
        CallFunction5 cf5 = luaManager.Global.Get<CallFunction5>("test3");
        cf5(800, "abc", 123, 45.05f, true, false, 'S');
        Debug.Log("------------------------------------------");

        // 使用LuaFunction进行变长参数函数调用
        Debug.Log("使用LuaFunction进行调用lua变长参数的函数");
        LuaFunction lf4 = luaManager.Global.Get<LuaFunction>("test3");
        lf4.Call(900, 131.9f, "Flower is Beautiful", true);
        
    }
}

6.C#调用Lua中的List和Dictionary

CallListDic.cs脚本如下.

关于由于在lua中的List和Dictionary中可以说同类的数据, 也可以是不同类型的数据, 因此, 乳沟知道数据类型就可以使用对应数据类型进行接收. 如果是不同的数据类型, 就需要考虑到了使用object来转换, 这就涉及到了装箱和拆箱的问题.

以下是lua总的代码

lua 复制代码
-- List的在C#中的映射
testList1 = { 1,2,3,4,5 }
testList2 = { "Fly", true, 0.4, 999 }

-- Dictionary在C#中的映射
testDic1 = {
	-- key的类型是一样的
	["1"] = 1,
	["2"] = 2,
	["3"] = 3,
	["4"] = 4
}

testDic2 = {
	-- key的类型是不一样的, 值的类型也不一样
	["1"] = 1,
	[true] = false,
	[false] = 3.8,
	[2] = 888
}

以下是CallListDic.cs的代码

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CallListDic : MonoBehaviour
{
    LuaManager luaManager;
    void Start()
    {
        luaManager = LuaManager.GetInstance();
        luaManager.Init();
        luaManager.DoLuaFile("Main");


        // 同类型List
        List<int> list1 = luaManager.Global.Get<List<int>>("testList1");
        print("--------------------------------------");
        for (int i = 0; i < list1.Count; i++)
        {
            print(list1[i]);
        }
        list1[0] = 100;// 浅拷贝 不会改变Lua中的内容
        List<int> list2 = luaManager.Global.Get<List<int>>("testList1");
        print(list2[0]);

        // 不指定类型 用object来存
        List<object> list3 = luaManager.Global.Get<List<object>>("testList2");
        for (int i = 0; i < list3.Count; i++)
        {
            print(list3[i]);
        }

        print("--------------------------------------");

        Dictionary<string, int> dic1 = luaManager.Global.Get<Dictionary<string, int>>("testDic1");
        foreach (string item in dic1.Keys)
        {
            print(item + "_" + dic1[item]);
        }
        dic1["1"] = 10000;
        Dictionary<string, int> dic2 = luaManager.Global.Get<Dictionary<string, int>>("testDic");
        print(dic2["1"]);
        // 浅拷贝 不改变Lua中的内容
        print("--------------------------------------");
        Dictionary<object, object> dic3 = luaManager.Global.Get<Dictionary<object, object>>("testDic2");
        foreach (object item in dic3.Keys)
        {
            print("key: " + item + "  Value: " + dic3[item]);
        }
    }
}

7.C#使用类调用lua

C# 调用lua的时候需要将定义和lua总的变量一致, 且C#中的变量是必须是public, 不然, 由于权限的问题无法完成lua和C#中的进行映射

以下是lua中的代码

lua 复制代码
-- lua中的类
testClass = {
	testInt = 10,
	testFLoat = 12.9,
	testString = "3.14",
	testBool = true,
	testFunc = function()
		print("TestFunc")
	end,
    -- 类中包含另外一个类
	testClassIN = 
	{
		testIn = 999
	}
}

以下是CallLuaClass.cs的代码

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class CalllLuaIn
{
    public int testIn;
}

public class CallLuaCall
{
    public int testInt;
    public float testFloat;
    public string testString;
    public bool testBool;
    public UnityAction testFunc;
    public CalllLuaIn testClassIN;

}
public class CallLuaClass : MonoBehaviour
{
    LuaManager luaManager;
    void Start()
    {
        luaManager = LuaManager.GetInstance();
        luaManager.Init();
        luaManager.DoLuaFile("Main");
        // C# Call lua的时候需要将定义和lua总的变量一致, 且C#中的变量是必须是public, 不然, 由于权限的问题无法完成lua和C#中的进行映射

        CallLuaCall clc = luaManager.Global.Get<CallLuaCall>("testClass");
        Debug.Log("C# Call Lua Class: " + clc.testInt);
        Debug.Log("C# Call Lua Class: " + clc.testFloat);
        Debug.Log("C# Call Lua Class: " + clc.testString);
        Debug.Log("C# Call Lua Class: " + clc.testBool);
        clc.testFunc();
        Debug.Log("类中类变量:" + clc.testClassIN.testIn);
    }

}

8.C#使用接口调用lua

使用接口来接收lua中的表, 需要点击编辑器上的按钮生成代码才可以被注册

C# 调用lua的时候需要将定义的构造器和lua总的变量一致, 且C#中的变量是必须是public, 不然, 由于权限的问题无法完成lua和C#中的进行映射, 由于是构造器的方式, 所以内存上是深拷贝

以下是lua中的代码

lua 复制代码
-- lua中的类, C#使用接口来调用
testInterface = {
	testInt = 10,
	testFloat = 12.9,
	testString = "3.14",
	testBool = true,
	testFunc = function()
		print("TestFunc")
	end
}

以下是CallLuaInterface.cs中的代码:

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using UnityEngine.Events;


[CSharpCallLua]
public interface CallLuaInterface
{ 
    // 接口中不能声明属性, 只能是容器
    int testInt { get; set;}
    float testFloat { get; set; }
    string testString { get; set; }
    bool testBool { get; set; }
    UnityAction testFunc { get; set; }
}
public class CallLuaInterface : MonoBehaviour
{
    LuaManager luaManager;
    void Start()
    {
        luaManager = LuaManager.GetInstance();
        luaManager.Init();
        luaManager.DoLuaFile("Main");

        CallLuaInterface clif = luaManager.Global.Get<CallLuaInterface>("testInterface");
        Debug.Log("C# 使用接口来调用lua中的类: " + clif.testInt);
        Debug.Log("C# 使用接口来调用lua中的类: " + clif.testFloat);
        Debug.Log("C# 使用接口来调用lua中的类: " + clif.testString);
        Debug.Log("C# 使用接口来调用lua中的类: " + clif.testBool);
        clif.testFunc();

        clif.testInt = 123456;
        CallLuaInterface clif2 = luaManager.Global.Get<CallLuaInterface>("testInterface");
        Debug.Log("修改C#实例中的变量后, 原来lua的变量修改为: " + clif2.testInt);
        // 注意, 在c#中使用接口来映射lua中的类, 是通过深拷贝进行的, 同时需要清空代码,重新生成代码
    }  
}

9.C#使用lua表调用lua

由于我们的luaManager中可以通过_Global获取lua中的所有数据, 因此表中表, 也是可以通过_Gloabl来获取.

lua中的代码如下

lua 复制代码
-- lua中的类, C#使用表来调用
testTable = {
	testInt = 10,
	testFloat = 12.9,
	testString = "3.14",
	testBool = true,
	testFunc = function()
		print("TestFunc")
	end
}

需要注意的是, 由于使用的是_Global表来获取里面的子表, 因此, 这是深拷贝.

CallLuaTable.cs代码如下:

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using XLua;
using UnityEngine;

public class CallLuaTable : MonoBehaviour
{
    LuaManager luaManager;
    void Start()
    {
        luaManager = LuaManager.GetInstance();

        luaManager.Init();
        luaManager.DoLuaFile("Main");
		// 使用_G表获得表
        LuaTable table = luaManager.Global.Get<LuaTable>("testTable");

        Debug.Log(table.Get<int>("testInt"));
        Debug.Log(table.Get<float>("testFloat"));
        Debug.Log(table.Get<bool>("testBool"));
        Debug.Log(table.Get<string>("testString"));
        // 使用xlu中的LuaFunction来获取函数
        table.Get<LuaFunction>("testFunc").Call();

        // 修改值
        // 说明在内存上是深拷贝
        table.Set("testInt", 3306);
        LuaTable table2 = luaManager.Global.Get<LuaTable>("testTable");
        Debug.Log(table2.Get<int>("testInt"));
    }
}
相关推荐
GesLuck3 小时前
C#开发实例1—彩票选号
开发语言·c#
neter.asia5 小时前
C# 窗体应用程序嵌套web网页,基于谷歌浏览器内核(含源码)
开发语言·c#
小猪写代码6 小时前
C语言:递归函数(新增)
算法·c#
两水先木示6 小时前
【Unity3D】ECS入门学习(七)缓存区组件 IBufferElementData
学习·unity·ecs
EQ-雪梨蛋花汤8 小时前
【WebAR-图像跟踪】在Unity中基于Imagine WebAR实现AR图像识别
unity·游戏引擎·ar
sukalot9 小时前
windows C#-在查询中返回元素属性的子集
开发语言·c#
向宇it10 小时前
【从零开始入门unity游戏开发之——C#篇32】C#其他不常用的泛型数据结构类、顺序存储和链式存储
java·开发语言·数据结构·unity·c#·游戏引擎
阿泽不想掉光头发11 小时前
C#实现调用DLL 套壳读卡程序(桌面程序开发)
java·开发语言·后端·websocket·http·c#
-凌凌漆-11 小时前
【C#】WPF设置Separator为垂直方向
c#
Marzlam12 小时前
C# IDisposable接口 与析构函数
开发语言·c#