xLua学习笔记_在C#脚本中使用xLua

xLua学习笔记_在C#脚本中使用xLua

https://www.cnblogs.com/guoyujam/p/12238215.html

  • 目录 (点击无法跳转的那种 ^_^ )
  • 开始
  • 加载Lua文件
  • 在C#脚本中,获取Lua中的变量
  • 在C#脚本中,获取Lua中的表
  • 在C#脚本中,获取Lua中的函数
  • 官方使用建议
  • 自定义Loader加载指定目录的Lua脚本
  • 待补充....

 

 

 


  • 开始

引入命名空间:

using XLua;

 

 创建Lua的运行环境:

LuaEnv luaenv = new LuaEnv();

这里有一段官方提示:

一个LuaEnv实例对应Lua虚拟机,出于开销的考虑,建议全局唯一。

 

释放Lua:

luaenv.Dispose();

 


 

  • 加载Lua文件

 注意,当你使用以下方法读取lua文件的时候

luaenv.DoString("require '文件名'");

这个文件名可以不用添加.lua或者.txt的后缀名,但是!这个文件的后缀名真正其实是.txt! 用.lua作为后缀名,Unity不会识别。

哪能不能不用txt作为后缀呢?

这里贴上一段xLua之FAQ中的一部分:

lua源码只能以txt后缀?

什么后缀都可以。

如果你想以TextAsset打包到安装包(比如放到Resources目录),Unity不认lua后缀,这是Unity的规则。

如果你不打包到安装包,就没有后缀的限制:比如自行下载到某个目录(这也是热更的正确姿势),然后通过CustomLoader或者设置package.path去读这个目录。

那为啥xLua本身带的lua源码(包括示例)为什么都是txt结尾呢?因为xLua本身就一个库,不含下载功能,也不方便运行时去某个地方下载代码,通过TextAsset是较简单的方式。

 


 

  • 在C#脚本中,获取Lua中的变量

首先,官方给的例子是这个样子的:

luaenv.Global.Get<int>("a")
luaenv.Global.Get<string>("b")
luaenv.Global.Get<bool>("c")

以上代码分别获取了Lua脚本中:

number类型的a       string类型的b       bool类型的c

 

这里需要注意的一点是:在获取number类型时,一定要注意接收的类型

当Lua中的number类型是小数时,使用Get<int>来获取会获取不到该值;返回值为0。

但是使用Get<double>(或者float)来获取number类型时,无论是整数还是小数,都可以获取到。

 


 

  • 在C#脚本中,获取Lua中的表

第一种方法,不推荐,官方描述:

映射到普通class或struct:

要注意的是,这个过程是值拷贝,如果class比较复杂代价会比较大。而且修改class的字段值不会同步到table,反过来也不会。

 方法如下:

1 -- 这是lua中的表
2 table = {
3 name = "xm",age = 12
4 }

需要在C#中定义一个与lua表中的元素名称,类型一样,而且必须是public的 (数量可以不一致)的class或者struct;

复制代码

//这是在C#中定义的类
class MyClass
{
    public string name;
    public int age;
}

复制代码

准备完毕后调用:

复制代码

1 MyClass mc = e.Global.Get<MyClass>("table");
2 print(mc.name);
3 print(mc.age);
4 //输出:
5 //xm
6 //12

复制代码

使用这种方法时,只能获取到你在C#类中定义的同名变量,若是你在表中定义了第三个变量,不去获取;又或是你在C#类中使用了不一样的名称变量,去获取,都不会得到这个值(不一样名称会为null),同时也不会报错。

 

 第二种方法,官方描述:

 映射到一个interface:

这种方式依赖于生成代码(如果没生成代码会抛InvalidCastException异常),代码生成器会生成这个interface的实例,如果get一个属性,生成代码会get对应的table字段,如果set属性也会设置对应的字段。甚至可以通过interface的方法访问lua的函数。

定义一个接口,需与lua表中的元素名称,类型一样 (数量可以不一致)

注意!这个接口必须是public的,且需要在上面加上[CSharpCallLua] ,并且要在Unity中重新生成xLua代码         这里有坑,未来补上

 接口:

复制代码

1 [CSharpCallLua]
2 public interface Itest
3 {
4     string name { get; set; }
5     int age { get; set; }
6 }

复制代码

调用方法还是和class的差不多:

1 Itest test = luaenv.Global.Get<Itest>("table");
2 Debug.Log(test.name);
3 Debug.Log(test.age);

第二种方法是引用传递,在C#中修改值,Lua中也会被修改。

 

 


 

  • 在C#脚本中,获取Lua中的函数

官方解释:

这种是建议的方式,性能好很多,而且类型安全。缺点是要生成代码(如果没生成代码会抛InvalidCastException异常)。

可以使用委托的方式:

1 [CSharpCallLua]
2 public delegate void testDelegate(int a,int b,int c,int d);

委托同样也需要添加[CSharpCallLua]且需要为public,最后需要在Unity中重新生成xLua才可以使用。这两项缺少一项,都会导致代码报错。

 

 调用方法:

1 testDelegate ad = luaenv.Global.Get<testDelegate>("add");
2 ad(1, 2, 3, 4);

Lua方面:

1 function add(a,b,c,d)
2     print(a+b+c+d)
3 end

如果有多个返回值,在定义委托的时候,加上out或者ref关键字可达到类似效果:

1 [CSharpCallLua]
2 public delegate void testDelegate(int a,out int o,ref int r);

 

注意:如果直接 luaenv.Dispose() 的话,会报错:

 

原因是C#中有变量正在引用着Lua中的东西,需要把C#中的那个变量置空才行。

1 ad = null;

这样操作后,Dispose就不会报错了。

 

 

还有一种直接映射到LuaFunction但是性能消耗比上一个要大,用法 及 官方解释:

1 LuaFunction f = luaenv.Global.Get<LuaFunction>("add");
2 f.Call(1, 2, 3, 4);

这种方式的优缺点刚好和第一种相反。(第一种是 “性能好很多,而且类型安全”)

使用也简单,LuaFunction上有个变参的Call函数,可以传任意类型,任意个数的参数,返回值是object的数组,对应于lua的多返回值。

 

 


  •  官方使用建议

结合以上的多种实现方法,官方给出的使用建议:

1、访问lua全局数据,特别是table以及function,代价比较大,建议尽量少做,比如在初始化时把要调用的lua function获取一次(映射到delegate)后,保存下来,后续直接调用该delegate即可。table也类似。

2、如果lua测的实现的部分都以delegateinterface的方式提供,使用方可以完全和xLua解耦:由一个专门的模块负责xlua的初始化以及delegateinterface的映射,然后把这些delegateinterface设置到要用到它们的地方。

 


 

  •  自定义Loader加载指定目录的Lua脚本

设置自定义Loader:

LuaEnv env = new LuaEnv();
env.AddLoader(MyLoader);

 

AddLoader这个函数的参数是一个 返回值为byte类型数组,参数是ref  string类型 的委托,为方便理解,下面贴出详细代码;

红色字体的MyLoader的定义如下:

1     public byte[] MyLoader (ref string filePath)
2     {
3         //方法体
4         return System.Text.Encoding.UTF8.GetBytes("这里是lua文件的路径位置"); 
5     }

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值