c#调用Lua代码

1. 默认加载文件路径

在这里插入图片描述

StreamingAssets目录下的.lua文件

注意要引用命名空间
using XLua;

        //Lua解析器 能够让我们在Unity中执行Lua
        //一般情况下 保持它的唯一性
        LuaEnv env = new LuaEnv();

        //执行Lua语言
        env.DoString("print('你好世界')");

        //执行一个Lua脚本 Lua知识点 :多脚本执行 require
        //默认寻找脚本的路径 是在 Resources下 并且 因为在这里
        //估计是通过 Resources.Load去加载Lua脚本  txt bytes等等
        //所以Lua脚本 后缀要加一个txt
        env.DoString("require('Main')");

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

        //销毁Lua解析器 
        env.Dispose();

2. lua 文件加载

2.1

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

void Start()
    {
        LuaEnv env = new LuaEnv();

        //xlua提供的一个 路径重定向 的方法
        //允许我们自定义 加载 Lua文件的规则
        //当我们执行Lua语言 require 时 相当于执行一个lua脚本
        //它就会 执行 我们自定义传入的这个函数
        env.AddLoader(MyCustomLoader);
        //最终我们其实 会去AB包中加载 lua文件 

        env.DoString("require('Main')");
    }

    //自动执行
    private byte[] MyCustomLoader(ref string filePath)
    {
        //通过函数中的逻辑 去加载 Lua文件 
        //传入的参数 是 require执行的lua脚本文件名
        //拼接一个Lua文件所在路径
        string path = Application.dataPath + "/Lua/" + filePath + ".lua";
        Debug.Log(path);

        //有路径 就去加载文件 
        //File知识点 C#提供的文件读写的类
        //判断文件是否存在
        if ( File.Exists(path) )
        {
            return File.ReadAllBytes(path);
        }
        else
        {
            Debug.Log("MyCustomLoader重定向失败,文件名为" + filePath);
        }

        return null;
    }

4. 全局变量获取

在这里插入图片描述
在这里插入图片描述

        LuaMgr.GetInstance().Init();

        LuaMgr.GetInstance().DoLuaFile("Main");

        //int local = LuaMgr.GetInstance().Global.Get<int>("testLocal");
        //Debug.Log("testLocal:" + local);

        //使用lua解析器luaenv中的 Global属性 
        int i = LuaMgr.GetInstance().Global.Get<int>("testNumber");
        Debug.Log("testNumber:" + i);
        i = 10;
        //改值
        LuaMgr.GetInstance().Global.Set("testNumber", 55);
        //值拷贝 不会影响原来Lua中的值
        int i2 = LuaMgr.GetInstance().Global.Get<int>("testNumber");
        Debug.Log("testNumber_i2:" + i2);

        bool b = LuaMgr.GetInstance().Global.Get<bool>("testBool");
        Debug.Log("testBool:" + b);

        float f = LuaMgr.GetInstance().Global.Get<float>("testFloat");
        Debug.Log("testFloat:" + f);

        double d = LuaMgr.GetInstance().Global.Get<double>("testFloat");
        Debug.Log("testFloat_double:" + d);

        string s = LuaMgr.GetInstance().Global.Get<string>("testString");
        Debug.Log("testString:" + s);
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using XLua;

/// <summary>
/// Lua管理器
/// 提供 lua解析器
/// 保证解析器的唯一性
/// </summary>
public class LuaMgr : BaseManager<LuaMgr>
{
    //执行Lua语言的函数
    //释放垃圾
    //销毁
    //重定向
    private LuaEnv luaEnv;


    /// <summary>
    /// 得到Lua中的_G
    /// </summary>
    public LuaTable Global
    {
        get
        {
            return luaEnv.Global;
        }
    }


    /// <summary>
    /// 初始化解析器
    /// </summary>
    public void Init()
    {
        //已经初始化了 别初始化 直接返回
        if (luaEnv != null)
            return;
        //初始化
        luaEnv = new LuaEnv();
        //加载lua脚本 重定向
        luaEnv.AddLoader(MyCustomLoader);
        luaEnv.AddLoader(MyCustomABLoader);
    }

    //自动执行
    private byte[] MyCustomLoader(ref string filePath)
    {
        //通过函数中的逻辑 去加载 Lua文件 
        //传入的参数 是 require执行的lua脚本文件名
        //拼接一个Lua文件所在路径
        string path = Application.dataPath + "/Lua/" + filePath + ".lua";

        //有路径 就去加载文件 
        //File知识点 C#提供的文件读写的类
        //判断文件是否存在
        if (File.Exists(path))
        {
            return File.ReadAllBytes(path);
        }
        else
        {
            Debug.Log("MyCustomLoader重定向失败,文件名为" + filePath);
        }


        return null;
    }


    //Lua脚本会放在AB包 
    //最终我们会通过加载AB包再加载其中的Lua脚本资源 来执行它
    //重定向加载AB包中的LUa脚本
    private byte[] MyCustomABLoader(ref string filePath)
    {
        //Debug.Log("进入AB包加载 重定向函数");
        从AB包中加载lua文件
        加载AB包
        //string path = Application.streamingAssetsPath + "/lua";
        //AssetBundle ab = AssetBundle.LoadFromFile(path);

        加载Lua文件 返回
        //TextAsset tx = ab.LoadAsset<TextAsset>(filePath + ".lua");
        加载Lua文件 byte数组
        //return tx.bytes;

        //通过我们的AB包管理器 加载的lua脚本资源
        TextAsset lua = ABMgr.GetInstance().LoadRes<TextAsset>("lua", filePath + ".lua");
        if (lua != null)
            return lua.bytes;
        else
            Debug.Log("MyCustomABLoader重定向失败,文件名为:" + filePath);

        return null;
    }


    public void DoLuaFile(string fileName)
    {
        string str = string.Format("require('{0}')", fileName);
        DoString(str);
    }

    public void DoString(string str)
    {
        if(luaEnv == null)
        {
            Debug.Log("解析器为初始化");
            return;
        }
        luaEnv.DoString(str);
    }

    public void Tick()
    {
        if (luaEnv == null)
        {
            Debug.Log("解析器为初始化");
            return;
        }
        luaEnv.Tick();
    }

    public void Dispose()
    {
        if (luaEnv == null)
        {
            Debug.Log("解析器为初始化");
            return;
        }
        try
        {
            luaEnv.Dispose();
            luaEnv = null;
            Debug.Log("释放成功");
        }
        catch (System.Exception ex)
        {
            Debug.Log(ex.Message);
        }
        
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using XLua;

//无参无返回值的委托
public delegate void CustomCall();

//有参有返回 的委托
//该特性是在XLua命名空间中的
//加了过后 要在编辑器里 生成 Lua代码
[CSharpCallLua]
public delegate int CustomCall2(int a);

[CSharpCallLua]
public delegate int CustomCall3(int a, out int b, out bool c, out string d, out int e);
[CSharpCallLua]
public delegate int CustomCall4(int a, ref int b, ref bool c, ref string d, ref int e);

[CSharpCallLua]
public delegate void CustomCall5(string a, params int[] args);//变长参数的类型 是根据实际情况来定的

public class Lesson5_CallFunction : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaMgr.GetInstance().Init();

        LuaMgr.GetInstance().DoLuaFile("Main");

        //无参无返回的获取
        //委托
        CustomCall call = LuaMgr.GetInstance().Global.Get<CustomCall>("testFun");
        call();
        //Unity自带委托
        UnityAction ua = LuaMgr.GetInstance().Global.Get<UnityAction>("testFun");
        ua();
        //C#提供的委托
        Action ac = LuaMgr.GetInstance().Global.Get<Action>("testFun");
        ac();
        //Xlua提供的一种 获取函数的方式 少用
        LuaFunction lf = LuaMgr.GetInstance().Global.Get<LuaFunction>("testFun");
        lf.Call();

        //有参有返回
        CustomCall2 call2 = LuaMgr.GetInstance().Global.Get<CustomCall2>("testFun2");
        Debug.Log("有参有返回:" + call2(10));
        //C#自带的泛型委托 方便我们使用
        Func<int, int> sFun = LuaMgr.GetInstance().Global.Get<Func<int, int>>("testFun2");
        Debug.Log("有参有返回:" + sFun(20));
        //Xlua提供的
        LuaFunction lf2 = LuaMgr.GetInstance().Global.Get<LuaFunction>("testFun2");
        Debug.Log("有参有返回:" + lf2.Call(30)[0]);

        //多返回值
        //使用 out 和 ref 来接收
        CustomCall3 call3 = LuaMgr.GetInstance().Global.Get<CustomCall3>("testFun3");
        int b;
        bool c;
        string d;
        int e;
        Debug.Log("第一个返回值:" + call3(100, out b, out c, out d, out e));
        Debug.Log(b + "_" + c + "_" + d + "_" + e);

        CustomCall4 call4 = LuaMgr.GetInstance().Global.Get<CustomCall4>("testFun3");
        int b1 = 0;
        bool c1 = true;
        string d1 = "";
        int e1 = 0;
        Debug.Log("第一个返回值:" + call4(200, ref b1, ref c1, ref d1, ref e1));
        Debug.Log(b1 + "_" + c1 + "_" + d1 + "_" + e1);
        //Xlua
        LuaFunction lf3 = LuaMgr.GetInstance().Global.Get<LuaFunction>("testFun3");
        object[] objs = lf3.Call(1000);
        for( int i = 0; i < objs.Length; ++i )
        {
            Debug.Log("第" + i + "个返回值是:" + objs[i]);
        }

        //变长参数
        CustomCall5 call5 = LuaMgr.GetInstance().Global.Get<CustomCall5>("testFun4");
        call5("123", 1, 2, 3, 4, 5, 566, 7, 7, 8, 9, 99);

        LuaFunction lf4 = LuaMgr.GetInstance().Global.Get<LuaFunction>("testFun4");
        lf4.Call("456", 6, 7, 8, 99, 1);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

在这里插入图片描述

		LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Main");

        //同一类型List
        List<int> list = LuaMgr.GetInstance().Global.Get<List<int>>("testList");
        Debug.Log("*******************List************************");
        for ( int i = 0; i <list.Count; ++i )
        {
            Debug.Log(list[i]);
        }
        //值拷贝 浅拷贝 不会改变lua中的内容
        list[0] = 100;
        List<int> list2 = LuaMgr.GetInstance().Global.Get<List<int>>("testList");
        Debug.Log(list2[0]);

        //不指定类型 object
        List<object> list3 = LuaMgr.GetInstance().Global.Get<List<object>>("testList2");
        Debug.Log("*******************List object************************");
        for (int i = 0; i < list3.Count; ++i)
        {
            Debug.Log(list3[i]);
        }

        Debug.Log("*******************Dictionary************************");
        Dictionary<string, int> dic = LuaMgr.GetInstance().Global.Get<Dictionary<string, int>>("testDic");
        foreach (string item in dic.Keys)
        {
            Debug.Log(item + "_" + dic[item]);
        }
        dic["1"] = 100000;
        //值拷贝 不会改变lua中的内容
        Dictionary<string, int> dic2 = LuaMgr.GetInstance().Global.Get<Dictionary<string, int>>("testDic");
        Debug.Log(dic2["1"]);

        Debug.Log("*******************Dictionary object************************");
        Dictionary<object, object> dic3 = LuaMgr.GetInstance().Global.Get<Dictionary<object, object>>("testDic2");
        foreach (object item in dic3.Keys)
        {
            Debug.Log(item + "_" + dic3[item]);
        }

在这里插入图片描述

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

public class CallLuaClass
{
    //在这个类中去声明成员变量
    //名字一定要和 Lua那边的一样
    //公共 私有和保护 没办法赋值
    //这个自定义中的 变量 可以更多也可以更少
    //如果变量比 lua中的少 就会忽略它
    //如果变量比 lua中的多 不会赋值 也会忽略
    public int testInt;
    public bool testBool;
    //public float testFloat;
    public float testString;
    public UnityAction testFun;

    public CallLuaInClass testInClass;

    public int i;

    public void Test()
    {
        Debug.Log(testInt);
    }
}

public class CallLuaInClass
{
    public int testInInt;
}

public class CallLuaInClassDic
{
    public Dictionary<string, int> testDic;
}

public class Lesson7_CallClass : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Main");

        CallLuaClass obj = LuaMgr.GetInstance().Global.Get<CallLuaClass>("testClas");
        Debug.Log(obj.testInt);
        Debug.Log(obj.testBool);
        //Debug.Log(obj.testFloat);
        Debug.Log(obj.testString);
        Debug.Log(obj.i);
        //Debug.Log("嵌套:" + obj.testInClass.testInInt);
        obj.testFun();
        //值拷贝 改变了它 不会改变Lua表里的内容
        obj.testInt = 100;
        CallLuaClass obj2 = LuaMgr.GetInstance().Global.Get<CallLuaClass>("testClas");
        Debug.Log(obj2.testInt);

        CallLuaInClassDic obj3 = LuaMgr.GetInstance().Global.Get<CallLuaInClassDic>("testClass");
        Debug.Log(obj3.testDic);
        Debug.Log(obj3.testDic.Count);

        foreach(string item in obj3.testDic.Keys)
        {
            Debug.Log(obj3.testDic[item]);
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using XLua;

//接口中是不允许有成员变量的 
//我们用属性来接受
//接口和类规则一样 其中的属性多了少了 不影响结果 无非就是忽略他们
//嵌套几乎和类一样 无非 是要遵循接口的规则
[CSharpCallLua]
public interface ICSharpCallInterface
{
    int testInt
    {
        get;
        set;
    }

    bool testBool
    {
        get;
        set;
    }

    float testFloat
    {
        get;
        set;
    }

    string testString
    {
        get;
        set;
    }

    UnityAction testFun
    {
        get;
        set;
    }

    float testFloat222
    {
        get;
        set;
    }
}

public class Lesson8_CallInterface : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Main");

        ICSharpCallInterface obj = LuaMgr.GetInstance().Global.Get<ICSharpCallInterface>("testClas");
        Debug.Log(obj.testInt);
        Debug.Log(obj.testBool);
        Debug.Log("新加的:" + obj.testFloat222);
        Debug.Log(obj.testString);
        obj.testFun();

        //接口拷贝 是引用拷贝 改了值 lua表中的值也变了
        obj.testInt = 10000;
        ICSharpCallInterface obj2 = LuaMgr.GetInstance().Global.Get<ICSharpCallInterface>("testClas");
        Debug.Log(obj2.testInt);


    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

不建议使用LuaTable和LuaFunction 效率低

在这里插入图片描述

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

public class Lesson9_CallLuaTable : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        LuaMgr.GetInstance().Init();
        LuaMgr.GetInstance().DoLuaFile("Main");

        //不建议使用LuaTable和LuaFunction 效率低
        //引用对象
        LuaTable table = LuaMgr.GetInstance().Global.Get<LuaTable>("testClas");
        Debug.Log(table.Get<int>("testInt"));
        Debug.Log(table.Get<bool>("testBool"));
        Debug.Log(table.Get<float>("testFloat"));
        Debug.Log(table.Get<string>("testString"));

        table.Get<LuaFunction>("testFun").Call();
        //改  引用
        table.Set("testInt", 55);
        Debug.Log(table.Get<int>("testInt"));
        LuaTable table2 = LuaMgr.GetInstance().Global.Get<LuaTable>("testClas");
        Debug.Log(table2.Get<int>("testInt"));

        table.Dispose();
        table2.Dispose();
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值