XLua
基本流程:引用命名空间using XLua ==> 创建虚拟机LuaEnv luaenv = new LuaEnv(); ==>运行lua语句luaenv.DoString("CS.UnityEngine.Debug.Log('hehe')"); ==>使用完毕释放luaenv.Dispose(释放前记得把所有委托注销避免报错)
C#调用Lua的文件
1.Lua文件的后缀必须时.lua.txt,file.lua.txt
2.Lua文件必须放在Resources文件夹下,不能是子文件夹,如果是streamingPath路径或其他路径的加载需要用特殊方法
3.Lua文件的编码格式必须是UTF-8
4.使用Lua的关键字require调用,不需要写文件后缀,只需要写文件名 (例:file.lua.txt require'file')
5,对于文件的返回值,需要写成return require 'file'才能获得
关于非Resources路径下lua文件,我们需要用自定义加载器加载
LuaEnv luaenv = new LuaEnv();
string lua = @"require 'hehe'" ==>文件名叫hehe.lua.txt
luaenv.AddLoader(CustemLoader);
/// <summary>
/// 自定义的加载器
/// </summary>
/// <param name="filePath">参数是require后的那个文件名字</param>
/// <returns></returns>
/// 返回值就是要执行的lua的转换之后的字节数组, 如果返回值是null证明我们未找到该lua文件
byte[] CustemLoader(ref string filePath)
{
//filePath: 参数是require后的那个文件名字
Debug.Log(filePath);
//byte[] bytes = System.Text.Encoding.UTF8.GetBytes("print('hello world')");
//文件所在的绝对路径
string path = Application.streamingAssetsPath + "/Lua/" + filePath + ".lua.txt";
//需要把lua的文件读取进来
if (!File.Exists(path))
{
//如果不存在该文件,直接返回null
return null;
}
StreamReader sr = new StreamReader(path, System.Text.Encoding.UTF8);
string lua = "";
try
{
lua = sr.ReadToEnd();
}
catch (System.Exception)
{
}
sr.Close();
if (lua == "")
{
//如果读取内容为空串,那么返回null,证明未找到该文件
return null;
}
else
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(lua);
return bytes;
}
}
/// <summary>
/// 从AB包中加载lua文件
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
byte[] CustemLoader(ref string filePath)
{
//加载AB包
AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath
+"/AB/lua");
//从ab包中加载所需要的lua文件
TextAsset lua = ab.LoadAsset<TextAsset>(filePath + ".lua");
if (lua != null)
{
return lua.bytes;
}
return null;
}
C#访问lua全局变量 ==> Luaenv.Global ==>从Global中获取变量和方法(全局的)
C#访问全局table
使用class或struct去映射table 值拷贝过程
T1 t1 = luaenv.Global.Get<T1>("tableName");
可以使用接口去映射 引用拷贝过程
IT1 it1 = luaenv.Global.Get<IT1>("tableName");
映射到字典或List中 值拷贝过程
List<object> list = luaenv.Global.Get<List<object>>("tableName");
Dictionary<string, object> dic = luaenv.Global.Get<Dictionary<string, object>>("tableName");
使用XLua提供的LuaTable来映射
LuaTable lt = luaenv.Global.Get<LuaTable>("tableName");
对于table中字符串作为键的键值对
string str = lt.Get<string>("tableName");
对于table中的数字类型的索引的键值对, 在取的时候需要指定键的类型和值的类型
string s = lt.Get<int,string>(3);
1.映射到类或结构体中(只能把table中的键值对映射到类中"公共变量"并且"变量名与键名一致",对于table与类的变量和键值的不对称没有任何影响)
2.使用接口映射(映射基本类型和table中的方法,table的键与接口的属性名或方法名对应上)
3.使用字典或list映射(list映射时,只能映射索引为数字且连续的,并且只能映射值与List指定类型一致的元素)
4.字典映射(相对的键值对一致才能映射)
5.用XLua的LuaTable映射
luaenv.DoString("require 'myluaFileName'");
int a = luaenv.Global.Get<int>("a_inLuaGlobal");
全局方法映射到委托
Func1 func1 = luaenv.Global.Get<Func1>("func1");
lua脚本中多返回值方法到委托
Func2 func2 = luaenv.Global.Get<Func2>("func2");
bool out1 = true;
int out2 = 0;
string out3 = "";
bool rt = func5(out outOne, ref outTwo, out outThree);
Debug.Log(" 第一个返回值: " + rt + " 2:" + out1 + " 3:" + out2 + " 4: " + out3);
当然在c#中也要定义相匹配的委托类型Func1/Func2 多返回值可以用多个参数out,ref去接
XLua支持函数重,支持可变参数方法
XLua支持C#默认参数 ==> int a =1
Lua调用C#枚举
CS.命名空间.枚举名.枚举值 或CS.枚举名.枚举值
Lua把字符串或数字转成枚举==>CS.命名空间.枚举名.__CastFrom(数字或字符串)(转化无效字符串会报错)
Lua调用C#委托和事件
XLua支持C#委托 因为Lua中没有+=/-=符号,对于空委托 mydel = func,不能mydel = mydel + func
MySpace{myClass{ Del del = null; void func(){...} }}
--lua对一个空委托进行赋值只能使用=。 而不能使用 a = a + b
CS.MySpace.myClass.del = CS.MySpace.myClass.Func;
--lua可以对一个非空委托使用a = a + b的形式把b添加到a里去
CS.MySpace.myClass.del = CS.MySpace.myClass.del + CS.MySpace.myClass.Func;
--lua可以对一个非空委托使用 a = a - b的形式进行把b从a中移除
CS.MySpace.myClass.del = CS.MySpace.myClass.del - CS.MySpace.myClass.Func;
静态的事件: CS.命名空间.类名.事件名('+或-',想要添加到事件里的方法名)
成员事件:对象名:事件名('+或-', 方法名) ==>对象名指的是在lua中对CS.命名空间.类名进行:
luatable = CS.MySpace.myClass()
luatable:eventDel('+',func)
func = function()
...
end
例:CS.MySpace.myClass.staticEvent('+', CS.MySpace.myClass.Func)
例:CS.MySpace.myClass.staticEvent('-', CS.MySpace.myClass.Func)
可以把lua的方法添加到事件里去的