【Unity】热更新之xLua C#获取Lua全局变量 / 函数

在Lua中,默认有一个_G表,记录了Lua文件中所有的全局变量,而xLua中LuaEnv给我们提供了一个Global的属性能让我们获得_G表。

C#获得 / 修改 Lua中的Number / Boolean / String类型的全局变量

在Unity工程中新建一个Lua文件,定义几个不同类型的全局变量如下

--MyLua.lua
num = 1
floatNum = 1.25
str = "abcde"
boolValue = true

在C#中获得以上Lua全局变量,这里因为我的Lua文件是放在Assets文件夹下新建的Lua文件夹中,所以下面用了自定义加载器,如果你还没了解自定义加载器,可以看一下我的上一篇文章【Unity】热更新之xLua C#调用Lua / 自定义加载器 / 加载并执行AB包中的Lua文件。
获得: Global提供了一个 Get<类型>(“Lua变量名”) 函数给我们获得Lua中的全局变量,这里注意"Lua变量名"必须和Lua文件中想要获取的变量名称一致,否则会出现报错。
修改: 修改同样使用Global提供的 Set(“Lua变量名”, 想要修改的值) 函数修改即可

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

public class LuaTest : MonoBehaviour
{
    LuaEnv luaEnv = new LuaEnv();

	//得到Lua中的_G表
    LuaTable Global => luaEnv.Global;
    
    // Start is called before the first frame update
    void Start()
    {
        luaEnv.AddLoader(CustomLoader_AssetLua);
        luaEnv.DoString("require('MyLua')");

		//获得Lua全局变量
        int num1 = Global.Get<int>("num");
        float num2 = Global.Get<float>("floatNum");
        string str1 = Global.Get<string>("str");
        bool boolValue = Global.Get<bool>("boolValue");
        Debug.Log(num1);
        Debug.Log(num2);
        Debug.Log(str1);
        Debug.Log(boolValue);

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

        //修改Lua中的全局变量的值
        Global.Set("num", 100);
        Global.Set("floatNum", 88.77);
        Global.Set("str", "qwer");
        Global.Set("boolValue", false);

        //重新获得对应数据
        num1 = Global.Get<int>("num");
        num2 = Global.Get<float>("floatNum");
        str1 = Global.Get<string>("str");
        boolValue = Global.Get<bool>("boolValue");

        Debug.Log(num1);
        Debug.Log(num2);
        Debug.Log(str1);
        Debug.Log(boolValue);
    }

	//自定义加载器
    byte[] CustomLoader_AssetLua(ref string filepath)
    {
        string path = Application.dataPath + "/Lua/" + filepath + ".lua";
        if (File.Exists(path))
        {
            return File.ReadAllBytes(path);
        }

        return null;
    }
}

运行Unity程序可以看到获得 / 修改 Lua中的全局变量已经成功了。
【Unity】热更新之xLua C#获取Lua全局变量 / 函数_第1张图片

C#获得Lua全局函数

Lua中的函数是一个特殊的数据类型(function),所以也是可以通过LuaEnv的Global获取的,C#可以用委托来存储Lua的函数。

无参数无返回值函数

在lua中定义一个无参数无返回值的函数

--MyLua.lua
function func1()
	print("无参无返回值函数")
end

存储Lua中的无参数无返回值函数有4种办法
1.使用Unity自带的UnityAction。(引用命名空间using UnityEngine.Events;)
2.用C#自带的Action。(引用命名空间using System;)
3.自己定义委托类型。
4.使用xLua提供的LuaFunction。

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

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

	//自己定义委托
    private delegate void Func1();

    // Start is called before the first frame update
    void Start()
    {
        luaEnv.AddLoader(CustomLoader_AssetLua);
        luaEnv.DoString("require('MyLua')");

        //无参数无返回值
        //UnityAction
        UnityAction luaFunc1 = Global.Get<UnityAction>("func1");
        luaFunc1();

        //自定义的委托类型
        Func1 CSharpFunc1 = Global.Get<Func1>("func1");
        CSharpFunc1();

        //C#自带的委托
        Action ac1 = Global.Get<Action>("func1");
        ac1();

        //LuaFunction
        LuaFunction lf1 = Global.Get<LuaFunction>("func1");
        lf1.Call();
    }

    byte[] CustomLoader_AssetLua(ref string filepath)
    {
        string path = Application.dataPath + "/Lua/" + filepath + ".lua";
        if (File.Exists(path))
        {
            return File.ReadAllBytes(path);
        }

        return null;
    }
}

有参数有返回值函数

在lua中定义一个有参数有返回值函数

--MyLua.lua
function func2(value1)
	print("有参有返回值函数,参数Value1 = " .. value1)
	return value1 + 10
end

存储Lua中的无参数无返回值函数有3种办法
1.用C#自带的Func。(引用命名空间using System;)
2.自己定义委托类型。
3.使用xLua提供的LuaFunction,LuaFunction中的Call方法参数是变长参数,所以可以传多个参数,返回值是object[],可以接收多个返回值。

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

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

    private delegate int Func1(int i);

    // Start is called before the first frame update
    void Start()
    {
        luaEnv.AddLoader(CustomLoader_AssetLua);
        luaEnv.DoString("require('MyLua')");

        Func<int, int> func = Global.Get<Func<int, int>>("func2");
        Debug.Log("返回值:" + func(200));

        Func1 delegateFunc = Global.Get<Func1>("func2");
        Debug.Log("返回值:" + delegateFunc(300));

        LuaFunction luaFunc = Global.Get<LuaFunction>("func2");
        Debug.Log("返回值:" + luaFunc.Call(400)[0]);
    }

    byte[] CustomLoader_AssetLua(ref string filepath)
    {
        string path = Application.dataPath + "/Lua/" + filepath + ".lua";
        if (File.Exists(path))
        {
            return File.ReadAllBytes(path);
        }

        return null;
    }
}

同理,无参数有返回值函数和有参数无返回值函数只要用相对应的委托去接收Lua中的函数即可。

有参数有多个返回值函数

在lua中定义有参数有多个返回值函数

luaFunc = function(value)
	return 1,2.4,true,"abc",value
end

存储Lua中的有参数有多个返回值函数有2种办法
1.自己定义委托类型。需要在委托上面添加[CSharpCallLua]特性,然后返回unity点击XLua - Generate Code生成代码。这里注意,Lua函数中的第一个返回值对应的是C#函数的返回值,其他返回值对应C#函数参数中的 out 参数,通过out参数获得其他返回值。
【Unity】热更新之xLua C#获取Lua全局变量 / 函数_第2张图片

2.使用xLua提供的LuaFunction,LuaFunction中的Call方法参数是变长参数,所以可以传多个参数,返回值是object[],可以接收多个返回值。

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

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

    [CSharpCallLua]
    public delegate int Func1(string inValue, out float v1, out bool v2, out string v3, out string v4);//访问权限必须是public,否则生成代码的时候会识别不到

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

        Func1 func1 = Global.Get<Func1>("luaFunc");
        float v1;
        bool v2;
        string v3;
        string v4;
        int returnValue = func1("这个是传入的参数", out v1, out v2, out v3, out v4);
        Debug.Log("第1个返回值:" + returnValue);
        Debug.Log("第2个返回值:" + v1);
        Debug.Log("第3个返回值:" + v2);
        Debug.Log("第4个返回值:" + v3);
        Debug.Log("第5个返回值:" + v4);
        
        Debug.Log("------------------------");

        LuaFunction func2 = Global.Get<LuaFunction>("luaFunc");
        object[] valueArr = func2.Call("这个是传入的参数 - LuaFunction");
        for(int i = 0; i < valueArr.Length; i++)
        {
            Debug.Log(valueArr[i]);
        }
    }

    /// 
    /// 自定义加载器,用来加载自定义路径中的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;
    }
}

运行Unity工程可以看到输出
【Unity】热更新之xLua C#获取Lua全局变量 / 函数_第3张图片
提示:如果遇到下面这个报错则检查一下是不是没加[CSharpCallLua]特性,注意加这个特性的委托访问权限必须是public,生成代码的时候才能识别,加上特性后返回unity点击XLua - Generate Code生成代码,生成完成后再次运行即可解决。
【Unity】热更新之xLua C#获取Lua全局变量 / 函数_第4张图片
以上就是这篇文章的所有内容了,此为个人学习记录,如有哪个地方写的有误,劳烦大佬指出,感谢,希望对各位看官有所帮助!

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