【Unity】热更新之xLua C# List、字典、类、接口映射Lua的Table类型

这篇文章记录一下C#如何获取Lua中的Table。关于如何获取Lua全局变量和函数的问题,可以看一下我的这篇文章【Unity】热更新之xLua C#获取Lua全局变量 / 函数。

C# List映射Lua中的Table(无自定义索引)

先在lua中定义两个table,一个类型一致,一个类型不一致。

--lua
list1 = { 1, 2, 3, 4, 5 }
list2 = { 7, 8.9, "abc", true }

C#中想要得到这两个table,同样是通过Global.Get来获得。
储存了不同类型元素的table映射到C#中可以用List存储。

//C#
List<int> intList = Global.Get<List<int>>("list1");
for(int i = 0; i < intList.Count; i++)
	Debug.Log(intList[i]);

Debug.Log("-----------------------");

List<object> objList = Global.Get<List<object>>("list2");
for (int i = 0; i < objList.Count; i++)
	Debug.Log(objList[i]);

运行后可以看到输出
【Unity】热更新之xLua C# List、字典、类、接口映射Lua的Table类型_第1张图片

C# Dictionary映射Lua中的Table(自定义索引)

lua中定义一个自定义索引的table

--lua
dic1 = {
	["a"] = 1,
	["b"] = 2,
	["c"] = 3,
	["d"] = 4
}

C#中应用Dictionary来获取table

//C#
Dictionary<string, int> dic1 = Global.Get<Dictionary<string, int>>("dic1");
foreach(string key in dic1.Keys)
{
	Debug.Log(key + " - " + dic1[key]);
}

运行可看到输出
【Unity】热更新之xLua C# List、字典、类、接口映射Lua的Table类型_第2张图片

C# 类映射 Lua中的Table

在Lua中定义一个table模拟C#中的类

--lua
testClass = {
	intV = 1,
	strV = "abc",
	boolV = false,
	floatV = 1.32,

	func = function()
		print("这是lua中的函数")
	end,

	--表中嵌套表,相当于类中包含一个类
	class2 = {
		value = 2
	}
}

C#中需要定义与Lua table一致的类,成员变量名需要和Lua table中的名字一致,访问权限必须是public。

public class TestClass
{
    public int intV;
    public string strV;
    public bool boolV;
    public float floatV;

    public UnityAction func;

	//这个是类中包含的另一个类
    public TestClass2 class2;
}

public class TestClass2
{
    public int value;
}

获取方法同样是通过Global.Get获取,完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using System.IO;
using UnityEngine.Events;

public class TestClass
{
    public int intV;
    public string strV;
    public bool boolV;
    public float floatV;

    public UnityAction func;

    public TestClass2 class2;
}

public class TestClass2
{
    public int value;
}

public class LuaTest : MonoBehaviour
{
    LuaEnv luaEnv = new LuaEnv();
    private LuaTable Global => luaEnv.Global;

    // Start is called before the first frame update
    void Start()
    {
        //添加自定义加载器
        luaEnv.AddLoader(MyCustomLoader);
        //luaEnv.AddLoader(MyABCustomLoader);

        luaEnv.DoString("require('MyLua01')");

		//获得Lua中的Table
        TestClass testClass = Global.Get<TestClass>("testClass");
        Debug.Log(testClass.intV);
        Debug.Log(testClass.strV);
        Debug.Log(testClass.boolV);
        Debug.Log(testClass.floatV);
        testClass.func();
        Debug.Log(testClass.class2.value);

    }

    /// 
    /// 自定义加载器,用来加载自定义路径中的Lua文件
    /// 
    /// Lua文件名
    /// Lua文件字节数组
    byte[] MyCustomLoader(ref string filepath)
    {
        //根据文件名,自定义加载路径,我这里是Asset文件夹下新建了一个Lua文件夹
        string path = Application.dataPath + "/Lua/" + filepath + ".lua";
        //这里判断一下文件是否存在	File需要引用System.IO命名空间
        if (File.Exists(path))
        {
            //如果存在,将文件读取出来并返回出去
            return File.ReadAllBytes(path);
        }
        //如果不存在就返回空
        return null;
    }
}

C#接口映射Lua的Table

同样在Lua中定义一个table

--lua
testClass = {
	intV = 1,
	strV = "abc",
	boolV = false,
	floatV = 1.32,

	func = function()
		print("这是lua中的函数")
	end
}

与类映射不同的是,接口不能有成员变量,必须用属性代替。所以,定义以下接口来映射table。接口必须添加[CSharpCallLua]特性,然后到unity中,点击XLua - Generate Code生成代码。(备注:如果生成代码后,又修改了接口,需要先点击XLua - Clear Generated Code清除生成的代码,然后再点击XLua - Generate Code生成代码。)

[CSharpCallLua]
public interface I_TestInterface
{
    int intV { get; set; }
    string strV { get; set; }
    bool boolV { get; set; }
    float floatV { get; set; }

    UnityAction func { get; set; }
}

完整代码如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using System.IO;
using UnityEngine.Events;

[CSharpCallLua]
public interface I_TestInterface
{
    int intV { get; set; }
    string strV { get; set; }
    bool boolV { get; set; }
    float floatV { get; set; }

    UnityAction func { get; set; }
}

public class LuaTest : MonoBehaviour
{
    LuaEnv luaEnv = new LuaEnv();
    private LuaTable Global => luaEnv.Global;

    // Start is called before the first frame update
    void Start()
    {
        //添加自定义加载器
        luaEnv.AddLoader(MyCustomLoader);
        //luaEnv.AddLoader(MyABCustomLoader);

        luaEnv.DoString("require('MyLua01')");

        I_TestInterface test = Global.Get<I_TestInterface>("testClass");
        Debug.Log(test.intV);
        Debug.Log(test.strV);
        Debug.Log(test.boolV);
        Debug.Log(test.floatV);
        test.func();

		//这里注意,接口修改对应的属性的值会直接影响到Lua中table中的值,下次再映射此table,就会发现值已经改了
        test.intV = 12345;
        I_TestInterface test2 = Global.Get<I_TestInterface>("testClass");
        Debug.Log(test2.intV);
    }

    /// 
    /// 自定义加载器,用来加载自定义路径中的Lua文件
    /// 
    /// Lua文件名
    /// Lua文件字节数组
    byte[] MyCustomLoader(ref string filepath)
    {
        //根据文件名,自定义加载路径,我这里是Asset文件夹下新建了一个Lua文件夹
        string path = Application.dataPath + "/Lua/" + filepath + ".lua";
        //这里判断一下文件是否存在	File需要引用System.IO命名空间
        if (File.Exists(path))
        {
            //如果存在,将文件读取出来并返回出去
            return File.ReadAllBytes(path);
        }
        //如果不存在就返回空
        return null;
    }
}

这里需要注意,接口修改对应的属性的值会直接影响到Lua中table中的值,下次再映射此table,就会发现值已经被修改了。
以上就是这篇文章的所有内容了,此为个人学习记录,如有哪个地方写的有误,劳烦大佬指出,感谢,希望对各位看官有所帮助!

你可能感兴趣的:(Unity,lua,unity,c#)