XLua教程之C#调用Lua
上一篇文章
XLua教程之入门篇-CSDN博客
在C#脚本中访问lua全局数据,特别是table以及function,代价比较大,建议尽量少做相关操作。
LuaEnv.Global.Get
用于获取一个全局变量,但是无法获取局部变量(用local修饰)
全局基本类型变量
支持int、float、double、bool、string类型
string value1 = luaenv.Global.Get<string>("stringValue");
Debug.Log($"string:{value1}");float value2 = luaenv.Global.Get<float>("floatValue");
Debug.Log($"float:{value2}");bool value3 = luaenv.Global.Get<bool>("boolValue");
Debug.Log($"bool:{value3}");double value4 = luaenv.Global.Get<double>("doubleValue");
Debug.Log($"double:{value4}");int value5 = luaenv.Global.Get<int>("intValue");
Debug.Log($"int:{value5}");
全局函数
测试:Lua脚本侧代码
--无参无返回值
function SayHi()print("hello world!")
end--有参有返回值
function GetNumSum(a,b,c)local result = a+b+c;print(result)return result
end--变长参数多返回值
function GetManyResult(...)local list = {...}local result1 = 0;for _,v in ipairs(list) doresult1 = result1 + vendlocal result2 = 1;for _,v in ipairs(list) doresult2 = result2 * vendreturn result1,result2
end
第一种方法 映射到委托delegate(推荐使用)
这种是建议的方式,性能好很多,而且类型安全。缺点是要生成代码(如果没生成代码会抛InvalidCastException异常)
1、先注册对应Lua函数的C#委托,并添加 [CSharpCallLua]标签。(无参无返回值可以不用添加该标签,xlua默认支持)
//无参无返回值
public delegate void NoParamNoReturn();//有参有返回值
[CSharpCallLua]
public delegate int XParamOneReturn(int a,int b,int c);//变长参数1返回值
[CSharpCallLua]
public delegate int XParam1Return(params int[] temp);
2、先清空生成的xlua插桩代码,再重新生成
3、调用
//无参无返回值
NoParamNoReturn func1 = luaEnv.Global.Get<NoParamNoReturn>("SayHi");
func1();//有参有返回值
XParamOneReturn func2 = luaEnv.Global.Get<XParamOneReturn>("GetNumSum");
var result1 = func2(1,2,3);
Debug.Log(result1);//变长参数1返回值
XParam1Return func3 = luaEnv.Global.Get<XParam1Return>("GetManyResult1");
int a =default(int);
int b =default(int);
var result2 = func3(1,2,3,4);
Debug.Log(result2);
第二种方法 映射到LuaFunction
LuaFunction上有个变参的Call函数,可以传任意类型,任意个数的参数,返回值是object的数组,对应于lua的多返回值。
//无参无返回值
LuaFunction func1 = luaEnv.Global.Get<LuaFunction>("SayHi");
func1.Call();//有参有返回值
LuaFunction func2 = luaEnv.Global.Get<LuaFunction>("GetNumSum");
var result1 = func2.Call(1,2,3);
foreach (var item in result1)
{Debug.Log(item);
}//变长参数多返回值
LuaFunction func3 = luaEnv.Global.Get<LuaFunction>("GetManyResult");
var result2 = func3.Call(1,2,3);
foreach (var item in result2)
{Debug.Log(item);
}
对比:
优先使用映射到委托方案
映射到XLua自带的LuaFunction,简单方便,但是会消耗性能;
映射到Delegate委托,官方建议,性能比LuaFunction要好很多,而且类型安全;但需要在自定义委托前添加[CSharpCallLua]特性标签
特性 | 映射到委托 (Delegate) | 映射到 LuaFunction |
---|---|---|
性能 | 极高 (接近原生C#调用) | 较低 (涉及查找、压参、调用、返回等一系列开销) |
用法 | 像调用普通C#委托一样 | 调用其 Call(...) 方法,传入参数数组 |
类型安全 | 强类型,编译时检查参数和返回值类型 | 弱类型,参数和返回值都是 object[] ,运行时易出错 |
内存开销 | 小 | 较大(每次调用可能产生临时 object[] 垃圾) |
适用场景 | 高频调用(如 Update 、UI事件回调) | 低频调用、一次性调用、参数数量/类型不固定 |
配置要求 | 需要标记 [CSharpCallLua] 并生成代码 | 无需任何额外配置,开箱即用 |
全局表
根据表的数据结构类型可以按照不同的情况,选择不同的映射形式。
如果表的形式类似于列表,可以映射到C#的List<T>。
如果表的形式类似于字典,可以映射到C#的Dictionary<T>。
如果表的形式类似于类,可以映射到C#的class。
映射到List<T>
List<int> list1 = luaEnv.Global.Get<List<int>>("list1");
foreach (var item in list1)
{Debug.Log(item);
}
映射到Dictionary<T>
Dictionary<int, string> dic = luaEnv.Global.Get<Dictionary<int, string>>("list2");
foreach (var item in dic)
{Debug.Log($"{item.Key}:{item.Value}");
}
映射到class
先根据lua表,声明对应C#类结构,再调用
public class Student
{public int id;public string name;public bool sex;public float score;
}Student student = luaEnv.Global.Get<Student>("Student");
Debug.Log($"{student.id} {student.name} {student.sex} {student.score}");
映射到LuaTable
xLua自带映射,兼容Lua表多种情况,不用定义c#类结构,开箱即用。但是性能消耗比较大,一般情况不推荐使用。
LuaTable student = luaEnv.Global.Get<LuaTable>("Student");
Debug.Log($"{student.Get<int>("id")}");
Debug.Log($"{student.Get<string>("name")}");
Debug.Log($"{student.Get<bool>("sex")}");
Debug.Log($"{student.Get<float>("score")}");
LuaEnv.Global.Set
用于修改一个全局变量
//string
luaenv.Global.Set("stringValue", "天天向上");
//float
luaenv.Global.Set("floatValue", 99.99);
//bool
luaenv.Global.Set("boolValue", false);
//double
luaenv.Global.Set("doubleValue", 9.999999999);
//int
luaenv.Global.Set("intValue", 438);