xLuaUnity热更新学习(1) - C#调用Lua

导入xlua 从github克隆xlua库复制Assets目录下的Plugins和XLua文件夹到自己的项目Assets目录下 C#调用Lua lua解析器 // 0. 引用命名空间 using XLua; // 1. 引入Lua解析器,以便在unity中执行lua // 一般情况保持唯一

导入xlua

从github克隆xlua库复制Assets目录下的Plugins和XLua文件夹到自己的项目Assets目录下

C#调用Lua

lua解析器

// 0. 引用命名空间
using XLua;
// 1. 引入Lua解析器,以便在unity中执行lua  
// 一般情况保持唯一  
LuaEnv env = new LuaEnv();  
//2. 执行lua语言  
// 如果传入后两个参数在报错时会输出  
env.DoString("print('hello world')"/*,文件信息,解释器信息*/);  
  
// 一般执行lua脚本默认加载路径在Resources文件夹里  
env.DoString("require('main')");  
  
// 清除Lua中没有手动释放的对象 GC垃圾回收  
// 一般在帧更新中定时执行,或者在切场景时执行  
env.Tick();  
// 销毁Lua解析器  
env.Dispose();

lua文件加载重定向

void Start()  
{  
    LuaEnv env = new LuaEnv();  
    // xlua提供的路径重定向方法  
    // 自定义加载lua文件的规则  
    // 当执行lua语言require时就会执行传入的这个自定义函数  
    env.AddLoader(MyCustomLoader);  
    env.DoString("require('lesson_2')");  
}  
  
// 这个自定义函数内找不到lua文件再去下一个自定义函数定义的路径找  
// 最后去默认路径即Resources路径找  
// 自动调用传入的filePath就是require('main')执行的lua脚本文件名如果是main那filePath的值就是main  
private byte[] MyCustomLoader(ref string filePath)  
{  
    // 拼接lua文件所在路径  
    string path = Application.streamingAssetsPath + "/lua 1/" + filePath + ".lua";  
    if (File.Exists(path))  
    {        return File.ReadAllBytes(path);  
    }    else  
    {  
        Debug.Log("重定向失败" + filePath);  
    }  
    return null;  
}

lua解析器管理器

using System.Collections;  
using System.Collections.Generic;  
using System.IO;  
using UnityEngine;  
using XLua;  
  
public class LuaMgr  
{  
    private static LuaMgr instance;  
    private string path;  
  
    public static LuaMgr getInstance()  
    {        if (instance == null)  
        {            instance = new LuaMgr();  
        }        return instance;  
    }  
    public LuaMgr init(string path = "/lua_1/")  
    {        if (env == null)  
        {            instance.env = new LuaEnv();  
            instance.path = path;  
            instance.env.AddLoader(MyCustomLoader);  
            instance.env.AddLoader(MyCustomABLoader);  
        }  
        return instance;  
    }    private byte[] MyCustomLoader(ref string filePath)  
    {        // 拼接lua文件所在路径  
        string path = Application.streamingAssetsPath + this.path + filePath + ".lua";  
        if (File.Exists(path))  
        {            return File.ReadAllBytes(path);  
        }        else  
        {  
            Debug.Log("重定向失败" + filePath);  
        }  
        return null;  
    }    /// <summary>  
    /// 自定义xlua文件路径AB包加载规则  
    /// </summary>  
    /// <param name="filePath"></param>    /// <returns></returns>    private byte[] MyCustomABLoader(ref string filePath)  
    {        // 拼接lua文件所在路径  
        string path = Application.streamingAssetsPath + "/lua";  
        AssetBundle ab = AssetBundle.LoadFromFile(path);  
        TextAsset asset = ab.LoadAsset<TextAsset>(filePath + ".lua");  
        if (asset)  
        {            return asset.bytes;  
        }        else  
        {  
            Debug.Log("重定向失败" + filePath);  
        }        return null;  
    }    /// <summary>  
    /// lua解析器  
    /// </summary>  
    private LuaEnv env;  
  
    /// <summary>  
    /// lua中的大G表  
    /// </summary>  
    public LuaTable global  
    {        get        {            return env.Global;  
        }  
    }  
    public void exec(string str,bool fileFlag = false)  
    {        if(!isEnvExist())  
            return;  
        env.DoString(fileFlag ?  "require('"+str+"')" : str );  
    }  
    public void gc()  
    {        if(!isEnvExist())  
            return;  
        env.Tick();  
    }  
    public void destory()   
    {  
        if(!isEnvExist())  
            return;  
        env.Dispose();  
        env = null;  
    }  
    public bool isEnvExist()  
    {        if (env == null)  
            Debug.Log("解析器不存在");  
        return env != null;  
    }}

调用lua全局变量

// c#代码
LuaMgr luaMgr = LuaMgr.getInstance().init().exec("lesson4");  
string hwStr = luaMgr.global.Get<string>("hwStr");  
Debug.Log(hwStr);
// lua代码
-- c#访问lua中全局变量
hwStr = 'hello world';

LueEnv env = new LuaEnv();
env.Global.get<T>("lua中声明的变量名") // 获取全局变量
env.Global.set<T>() // 设置

// 这里get进行的是值拷贝不会改变lua中的值如果要改变lua中的值要用set

调用lua全局函数

  
using System;  
using UnityEngine;  
using UnityEngine.Events;  
using XLua;  
  
[CSharpCallLua]  
public delegate int custom(int a); // 一个参数一个返回值  
  
[CSharpCallLua]  
public delegate int custom1(int a ,out int v1,out bool v2); // 多个返回值用out  
  
[CSharpCallLua]  
public delegate int custom2(int a,params object[] args); // 变长参数  
public class Lesson_4 : MonoBehaviour  
{  
    void Start()  
    {        LuaMgr luaMgr = LuaMgr.getInstance().init().exec("lesson4");  
        string hwStr = luaMgr.global.Get<string>("hwStr");  
        Debug.Log(hwStr);  
        Func<int,int> luaFunction = luaMgr.global.Get<Func<int, int>>("hwFun"); // 一个参数一个返回值还可以这么写  
        custom1 custom1 = luaMgr.global.Get<custom1>("hwFun"); // 多返回值或者变长参数  
        int i1;  
        bool b1;        Debug.Log(custom1(10,out i1,out b1));  
        Debug.Log(luaFunction(10));;  
    }  
    }

[!warning] 注意
改完c#调用lua相关的代码要用xlua重新生成代码

lua表映射到C#的List和Dictionary

LuaTable luaTable = LuaMgr.getInstance().init().exec("lesson4").global;  
// 相同类型列表  
// lua list1 = {1,2,3,4,5}  
List<int> ints = luaTable.Get<List<int>>("list1");  
foreach (int i in ints)  
{  
    Debug.Log(i);  
}  
  
Debug.Log("==================");  
// 不同类型列表  
//lua list2 = {1,'a',true}  
List<object> objects = luaTable.Get<List<object>>("list2");  
foreach (object o in objects)  
{  
    Debug.Log(o);  
}  
  
Debug.Log("==================");  
// 相同类型键,不同类型值  
/*  
    lua dic1 = {            ['id'] = 1,            ['age'] = 18,            ['name'] = 'test'        } */Dictionary<string,object> dictionary = luaTable.Get<Dictionary<string, object>>("dic1");  
foreach (string dictionaryKey in dictionary.Keys)  
{  
    Debug.Log(dictionaryKey);  
    Debug.Log(dictionary[dictionaryKey]);  
}  
  
Debug.Log("==================");  
// 不同键类型,不同值类型  
/*  
    lua dic2 = {        [false] = 1,        ['age'] = 18,        ['name'] = 'test'    } */Dictionary<object,object> dictionary2 = luaTable.Get<Dictionary<object, object>>("dic2");  
foreach (object dictionaryKey in dictionary2.Keys)  
{  
    Debug.Log(dictionaryKey);  
    Debug.Log(dictionary2[dictionaryKey]);  
}

lua表映射到类

using System.Collections;  
using System.Collections.Generic;  
using UnityEngine;  
using UnityEngine.Events;  
using XLua;  
  
public class testIntClass  
{  
    public int testInt;  
}  
public class TableToClass  
{     
// 访问权限必须为公共,私有和保护没法赋值,变量名要和lua那边语音  
    // 成员变量数量不必跟lua相符可多可少,少了忽略,多了也不会赋值  
    public int testint;  
    public bool testbool;  
    // 成员方法用Action映射  
    public UnityAction testFun;  
    // 嵌套类也能正常赋值  
    public testIntClass testIntClass;  
}  
public class Lesson_6 : MonoBehaviour  
{  
    void Start()  
    {        /*  
        lua class1 = {                testint = 1;                testbool = true;                testFun = function ()                    print("表映射到类")  
                end;                testIntClass = {                    testInt = 7                }            }         */        LuaTable luaTable = LuaMgr.getInstance().init().exec("lesson4").global;  
        TableToClass tableToClass = luaTable.Get<TableToClass>("class1");  
        Debug.Log(tableToClass.testint);  
        tableToClass.testFun();  
        Debug.Log(tableToClass.testIntClass.testInt);  
    }}

lua表映射到接口

[!info] 提示
跟表到类差不多就是要在c#的接口上加[CSharpCallLua]然后用xLua生成代码

[!warning] 注意
只有映射到接口是引用拷贝对值修改会影响到lua中的值

lua表映射到LuaTable和LuaFunction不建议使用效率低

/*  
lua class1 = {  
        testint = 1;        testbool = true;        testFun = function ()            print("表映射到类")  
        end;        testIntClass = {            testInt = 7        }    } */LuaTable luaTable = LuaMgr.getInstance().init().exec("lesson4").global;  
LuaTable table = luaTable.Get<LuaTable>("interface1");  
int i = table.Get<int>("testint");  
LuaFunction i = table.Get<LuaFunction>("testint"); 
Debug.Log(i);
LICENSED UNDER CC BY-NC-SA 4.0
评论