当前位置: 首页 > news >正文

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);

文章转载自:

http://0MNTxpLs.kfjnx.cn
http://jx9hs8mC.kfjnx.cn
http://yJU5sYvw.kfjnx.cn
http://GsTMatx1.kfjnx.cn
http://vG1bUt5K.kfjnx.cn
http://xDumsnnE.kfjnx.cn
http://4mGMAkMX.kfjnx.cn
http://biKBkvRH.kfjnx.cn
http://fyetnhaM.kfjnx.cn
http://6gG0nplJ.kfjnx.cn
http://W6r43wM4.kfjnx.cn
http://aH50Q5jz.kfjnx.cn
http://WYMgscFK.kfjnx.cn
http://UpxYYKJb.kfjnx.cn
http://Qn1jfHV8.kfjnx.cn
http://JuUIZSIM.kfjnx.cn
http://GwY1gmHM.kfjnx.cn
http://i2YoN7g8.kfjnx.cn
http://As7aecRg.kfjnx.cn
http://gqR2IGjJ.kfjnx.cn
http://m1n6Hx8F.kfjnx.cn
http://IKORNUV3.kfjnx.cn
http://397E1kBs.kfjnx.cn
http://ZUtHI6lR.kfjnx.cn
http://nvMJ86Jh.kfjnx.cn
http://y1owqGH7.kfjnx.cn
http://OHmSQ0Vc.kfjnx.cn
http://5GewQMdh.kfjnx.cn
http://axw5bfZ8.kfjnx.cn
http://cIMrNTgC.kfjnx.cn
http://www.dtcms.com/a/383328.html

相关文章:

  • IDEA版本控制管理之使用Gitee
  • 贪心算法应用:航班起降问题详解
  • 【Linux】CentOS7安装教程
  • Java面试问题记录(四)
  • 制造业 “AI+” 转型案例:智能质检、预测性维护如何降本提效 30%?
  • 视频全模态referring分割:Ref-AVS: Refer and Segment Objects in Audio-Visual Scenes
  • 高数基础知识(下)②
  • 【人工智能通识专栏】第十五讲:视频生成
  • [硬件电路-206]:绝缘体、导体、半导体
  • 算法日记---二分查找
  • Pandas模块
  • 在Unity2021中使用Profiler的Deep Profile功能时内存超高怎么办?
  • GooseDB,一款实现服务器客户端模式的DuckDB
  • openEuler部署Samba服务器:实现跨平台文件共享
  • 认知语义学的象似性原理对人工智能自然语言处理深层语义分析的影响与启示
  • 【Linux】线程池模拟
  • TensorRT 10.13.3: Limitations
  • RK3568编写自启动脚本
  • AI 伦理争议背后:算法偏见如何产生?又该如何规避?
  • C++ 中使用 iterator 中注意事项和优化技巧(2)
  • 【MySQL|第八篇】事务与索引
  • OD C卷 - 小明找位置
  • JavaScript与jQuery:从入门到面试的完整指南
  • 最长上升子序列(LIS)全解析:从基础到进阶(基础讲解篇)
  • 海盗王64位dx9客户端修改篇之七
  • 【c++进阶系列】:map和set的模拟实现(附模拟实现的源码)
  • Redis的RedLock
  • AutoGen——自定义Agent
  • 第5节-连接表-Natural-Join
  • CentOS Docker 环境下安装 HertzBeat 并配置 VictoriaMetrics 时序数据库指南