|
Xlua
C#调用Lua
lua解析器
lua解析器可以让我们在unity中执行Lua,一般情况下,我们会保证它在unity中的唯一性。- //创建一个lua解析器LuaEnv env =newLuaEnv();//执行Lua语言
- env.DoString("print('你好世界')");//像上面这样一句一句的执行lua脚本是非常不好的,所以可以使用lua脚本加载的知识来解决这个问题。//xlua默认的脚本寻找路径是在Resources文件夹中,但是由于unity并不能识别Lua文件,所以直接加载时会报错的。解决方案是我们将lua后缀多加一个txt,将其转换为文本文件。
- env.DoString("require('Main')");//此方法可以帮助我们清除Lua中我们没有手动释放的对象,相当于垃圾回收。//我们可以在帧更新中定时执行,也可以在切换场景时执行。
- env.Tick();//销毁Lua解析器,一般会用的会比较少,因为我们之前说过了,我们基本会保证Lua解析器在unity中是全局唯一的。
- env.Dispose();
复制代码 lua文件重定向
- //需要调用此方法来添加新的路径,参数为委托类型//delegate byte[] CustomLoader(ref string filepath)
- env.AddLoader(NewLoader);//这里我们写一个方法并传进去privatebyte[]NewLoader(refstring filepath){//路径拼接需要加上后缀string path = Application.dataPath +"/Lua/"+ filepath +".lua";if(File.Exists(path)){return File.ReadAllBytes(path);}returnnull;}//由于委托可以注册多个方法,所以xlua的文件重定向查找方案也是优先查找委托中所有的路径,最后查找默认路径Resources。//一旦找到对应文件就会返回。不再继续
复制代码 获取全局变量
- //首先我们需要编辑一个test.lua脚本并书写一下信息print("Test脚本");
- testNumber =1;
- testBool =true;
- testFloat =1.2;
- testString ="你好";//在之前的LuaManager中我们添加了一个Global属性,用于获得lua解析器的_G表。//我们调用xlua的Global中的get方法来获取lua解析器读取的lua脚本中_G表所存放的全局变量。//注意,字符串内容需要与lua中的变量名一致。//这里是值拷贝,就算使用临时变量接受了返回值并进行改变也不会影响Lua脚本中的值。print(LuaManager.GetInstance.Global.Get<int>("testNumber"));print(LuaManager.GetInstance.Global.Get<bool>("testBool"));//虽然lua只有一种数值类型number,但是我们可以根据其内容来在C#中为其赋予类型print(LuaManager.GetInstance.Global.Get<float>("testFloat"));print(LuaManager.GetInstance.Global.Get<string>("testString"));//想要改变Lua脚本中的值,我们需要使用Global提供给我们的Set方法。
- LuaManager.GetInstance.Global.Set("testNumber",5);print(LuaManager.GetInstance.Global.Get<int>("testNumber"));
复制代码 获得全局函数
- //我们在test.lua中添加新成员
- testFunc1 =function()print("这是一个无参无返回值的函数");
- end
- testFunc2 =function(param)print("这是一个有参有返回值的函数");return param +1;
- end
- testFunc3 =function()print("这是一个多返回值的函数");return1,2,"123";
- end
- testFunc4 =function(...)
- arg ={...};print("这是一个有变长参数的函数");for k,v inpairs(arg)doprint(k,v)
- end
- end
- //总的来说,获得lua的全局函数需要使用到委托。//这里我们可以使用自定义委托,C#提供的标准委托,或是使用Xlua提供的委托。//注意使用Xlua提供的委托可能发生拆箱装箱//我们先来看第一种情况,无参无返回值,我们直接使用Action委托来接受。Action func1 = LuaManager.GetInstance.Global.Get<Action>("testFunc1");
- func1.Invoke();//第二种情况,有参有返回值,我们直接使用Func委托来接受。
- Func<int,int> func2 = LuaManager.GetInstance.Global.Get<Func<int,int>>("testFunc2");
- func2.Invoke(10);//第三种情况,多返回值的函数,我们需要自定义委托来接受。首先我们自定义委托//当我们要使用自定义委托来接受lua中的全局函数时,我们需要为委托添加[CSharpCallLua]特性,并重新加载。[CSharpCallLua]publicdelegatevoidFuncHandler(outint paramA,outint paramB,outstring paramC);//使用此委托接受FuncHandler func3 = LuaManager.GetInstance.Global.Get<FuncHandler>("testFunc3");int paramA;int paramB;string paramC;
- func3.Invoke(out paramA,out paramB,out paramC);//第四种情况,要求输入一个变长参数,我们依旧需要自定义委托来接受。[CSharpCallLua]publicdelegatevoidFuncHandler2(paramsobject[] array);FuncHandler2 func4 = LuaManager.GetInstance.Global.Get<FuncHandler2>("testFunc4");
- func4.Invoke(1,2,3,"qwe",true);
复制代码 List,Dictionary映射Table
- //使用List和Dictionary映射Table和之前说过的获得全局变量是一样的。//来到lua脚本我们添加一些表
- testList1 ={1,2,3,4,5,6};
- testList2 ={1,2,3,"123",true,false};
- testDic1 ={["1"]=1,["2"]=2,["3"]=3,["4"]=4,}
- testDic2 ={["1"]=1,["2"]=2,["3"]=true,["4"]=false,}//来到C#使用list或者dictionary直接接受//注意这里的接受依旧是值拷贝
- List<int> testList1 = LuaManager.GetInstance.Global.Get<List<int>>("testList1");foreach(var item in testList1){print(item);}
- List<object> testList2 = LuaManager.GetInstance.Global.Get<List<object>>("testList2");foreach(var item in testList2){print(item);}
- Dictionary<string,int> testDic1 = LuaManager.GetInstance.Global.Get<Dictionary<string,int>>("testDic1");foreach(var key in testDic1.Keys){print($"{key}_{testDic1[key]}");}
- Dictionary<string,object> testDic2 = LuaManager.GetInstance.Global.Get<Dictionary<string,object>>("testDic2");foreach(var key in testDic2.Keys){print($"{key}_{testDic2[key]}");}
复制代码 类映射Table
- //使用C#类映射lua中的类表//首先我们先在lua中写一个类表,其中包含number类型,string类型,boolean类型和function类型
- testClass ={
- myInt =1,
- myString ="你好",
- myBool =true,
- myFunc =function()print("testClass的函数");
- end
- }//接下来我们来书写C#中准备接受这个表的类//其中,类名实没有要求的,但是在这个类中声明的成员变量名称需要和lua中的名称一致,这也是首次要求名称对应。//类的成员变量需要是公共的,或者internal,其他类型将无法赋值。//我们不需要将lua中声明的类型在这里全部声明;不论是多出来的变量还是缺少的变量,Xlua都会选择忽略。publicclassCallLuaClass{publicint myInt;publicstring myString;publicbool myBool;publicAction myFunc;}//使用类映射table依旧是值拷贝
复制代码 接口映射Table
接口映射Table和类大同小异,但在使用时需要注意:
接口需要统一使用属性来接受lua脚本中的成员。使用接口映射Table时,需要和自定义委托一样加上特性并重新编译。如果改变了接口的内容,一定要先清除在编译。接口是引用拷贝,改变接口的值,lua中的值也会改变。
LuaTable,LuaFunction
首先要说的是,官方不推荐使用luaTable接收lua中的Table,也不推荐使用LuaFunction接收Lua中的function,他们执行效率低,且需要手动释放资源。
但需要注意的是。LuaTable和LuaFunction是引用拷贝,可以通过set方法改变lua脚本中的值。
*Lua调用C#
Lua使用C#类
- print("*********Lua调用C#类相关知识点*********");--对于lua调用C#的方法,我们一定是通过C#先进入Lua的--通过DoString方法进入--lua中使用C#的类非常简单--固定套路--CS.命名空间.类名--Unity的类 比如 GameObject , Transform等等 可以通过CS.UnityEngine.类名进行调用--CS.UnityEngine.GameObject--CS.UnityEngine.Transformprint("通过C#中的类在Lua中实例化一个游戏对象");--由于Lua中没有new,所以在Lua中我们有另外的语法来创建对象。--在Lua中类名括号就是在实例化对象,默认的调用的相当于就是无参构造函数。--调用无参构造函数local gameObject1 = CS.UnityEngine.GameObject();--调用有参构造函数local gameObject2 = CS.UnityEngine.GameObject("有参构造函数对象");--为了方便使用并节约性能,定义全局变量存储C#中的类--相当于取了一个别名
- GameObject = CS.UnityEngine.GameObject;local gameObject3 =GameObject("这是一个取了别名的游戏对象");--类中的静态对象可以直接使用.运算符来调用local gameObject4 = GameObject.Find("这是一个取了别名的游戏对象");--得到对象中的成员变量,直接使用.运算符即可print(gameObject4.transform.position);
- Debug = CS.UnityEngine.Debug;
- Debug.Log(gameObject4.transform.position);--如果使用对象中的成员方法一定要使用:
- Vector3 = CS.UnityEngine.Vector3;
- gameObject4.transform:Translate(Vector3.right);
- Debug.Log(gameObject4.transform.position);--使用不继承Mono的普通类,首先在C#中创建一个Test类
- Test = CS.Test;--创建一个对象local test =Test();
- test:Speak("123");--继承Mono的类。--注意继承Mono的类是不可以直接new的,我们需要使用AddComponent方法local gameObject5 =GameObject("加脚本测试");--通过GameObject的AddComponent添加脚本--Xlua提供了一个重要的方法typeof可以获得类的Type--Xlua中不支持无参泛型函数,所以我们需要使用AddComponent的另一个重载
- gameObject5:AddComponent(typeof(CS.Test1_LuaEnv));
复制代码 Lua使用C#枚举
- print("*********Lua调用C#枚举相关知识点*********");--Lua调用C#的枚举,和调用C#的类相似,直接使用.运算符来使用其枚举值--调用Unity中的默认枚举--首先参照lua调用类,我们先将枚举的命名空间保存
- PrimitiveType = CS.UnityEngine.PrimitiveType;
- GameObject = CS.UnityEngine.GameObject;--unity中创建默认几何体的代码local obj = GameObject.CreatePrimitive(PrimitiveType.Cube);--自定义枚举,使用方法和unity的默认枚举一样,但需要注意命名空间--我们联合枚举转换一起来说
- E_MyEnum = CS.E_MyEnum;print(E_MyEnum.idle);--数值转枚举local enum1 = E_MyEnum.__CastFrom(1);print(enum1);--字符串转枚举local enum2 = E_MyEnum.__CastFrom("atk");print(enum2);
复制代码 Lua使用C#数组,List,Dictionary
- print("*********Lua调用C#数组相关知识点*********");--需要注意,虽然我们在Lua中使用表来模拟数组,list,dictionary,但是当lua调用C#时,我们要遵守C#的使用规则。--首先我们现在Lua中创建一个C#的数组--这里我们调用C#中Array基类的CreateInstance方法来创建,具体参数信息需要查阅C#--这里我们使用的方法第一个参数传入type,第二个参数传入容量local array = CS.System.Array.CreateInstance(typeof(CS.System.Int32),10);--获得数组的长度,这里调用了C#中的成员变量print(array.Length);--访问数组的元素print(array[0]);--数组遍历,这里需要注意,虽然Lua的索引是从1开始,但是我们使用的是C#的数组,其索引是从0开始的。--注意Lua中的for循环遍历一定要减1for i=1,array.Length -1doprint(array[i]);endprint("*********Lua调用C#List相关知识点*********");--首先我们还是先创建一个List对象,这里有两种方式。--老版本--其中CS.System.Collections.Generic是List泛型的命名空间,List`1指的是此泛型有一个泛型参数。local list = CS.System.Collections.Generic["List`1[System.String]"]();
- list:Add("5555");print(list[0]);--新版本local List_String = CS.System.Collections.Generic.List(CS.System.String);local list2 =List_String();
- list2:Add("123");print(list2[0]);--输出长度print(list2.Count);print("*********Lua调用C#Dictionary相关知识点*********");--我们还是先来创建一个字典local dictionary_Int_Vector3 = CS.System.Collections.Generic.Dictionary(CS.System.String, CS.UnityEngine.Vector3);local dic =dictionary_Int_Vector3();
- dic:Add("123",CS.UnityEngine.Vector3.right);--除了int类型的键,其他无法通过索引直接获得,这里会直接报空print(dic["123"]);--我们通过以下方法来获得键值--1. TryGetValueprint(dic:TryGetValue("123"));--2. get_Item, set_Itemprint(dic:get_Item("123"));
- dic:set_Item("123",nil);print(dic:get_Item("123"));
复制代码 Lua使用C#拓展方法
- print("*********Lua调用C#List相关知识点*********");local ExMethodDemo = CS.ExMethodDemo();--Lua调用C#的拓展方法时,需要在拓展方法的类上面加上[LuacallCSharp]这个特性,并重新加载--使用拓展方法和使用成员方法一样使用:,毕竟拓展方法本身就是将自己作为参数传进去了。
- ExMethodDemo:Eat();--[[
- 总结:
- 1. 想要在Lua中使用拓展方法,就一定要加上[LuacallCSharp]特性。
- 2. 建议Lua中要使用的C#类都使用这个特性,可以提升性能。
- 3. Xlua是通过反射来调用C#类的,当我们加了上述特性并重新加载代码后,相当于提前做了工作。
- ]]
复制代码 Lua使用ref和out
- print("*********Lua调用C#ref和out相关知识点*********");local RefAndOut = CS.RefAndOut();--C#中的ref参数会以多返回值的形式返回给Lua。--如果函数存在返回值,则第一个默认返回该返回值。--之后返回的结果就是ref的结果,从左到右一一对应。--ref参数需要传入一个默认值来占位,这点和C#中使用是非常相似的。local paramA,paramB,paramC = RefAndOut:RefTest(1,0,0,1);print(paramA);print(paramB);print(paramC);--C#中的out参数会以多返回值的形式返回给Lua。--如果函数存在返回值,则第一个默认返回该返回值。--之后返回的结果就是out的结果,从左到右一一对应。--与ref不同,out参数不需要占位,当然如果你传入参数也没有事。local paramA,paramB,paramC = RefAndOut:OutTest(2,1);print(paramA);print(paramB);print(paramC);--ref和out的综合使用,总体区别在于ref需要占位,out不需要local paramA,paramB,paramC = RefAndOut:RefOut(2,1,1,1);print(paramA);print(paramB);print(paramC);
复制代码 Lua使用C#重载方法
- print("*********Lua调用C#重载方法相关知识点*********");--虽然lua自己不支持重载函数的书写,但是可以调用C#中的重载函数--原因是lua中对于相同变量的函数赋值会覆盖之前赋值的函数,所以不能重载函数是,但如果调用C#的话很明显就不会存在这个问题。local CallOverrideFunc = CS.LuaCallOverride();
- CallOverrideFunc:CallOverrideWithParam();--注意,由于lua中在数值类型上只支持number类型,所以对于C#中参数个数相同,数值精度不同的重载无法正确获得。--我们要尽量避免这种写法,或者使用Xlua提供给我们的反射解决方案。--需要注意的是,此方案毕竟是通过反射实现的,性能较差,不到万不得已的情况下不要使用。print(CallOverrideFunc:CallOverrideWithParam(10));print(CallOverrideFunc:CallOverrideWithParam(10.2));--反射解决方案--首先通过反射获得需要使用的方法local method1 =typeof(CS.LuaCallOverride):GetMethod("CallOverrideWithParam",{typeof(CS.System.Int32)});local method2 =typeof(CS.LuaCallOverride):GetMethod("CallOverrideWithParam",{typeof(CS.System.Single)});--通过Xlua提供的tofunction方法转换为lua函数--一般我们只转换一次,之后重复使用local luafunc1 = xlua.tofunction(method1);local luafunc2 = xlua.tofunction(method2);--转换完成后,需要注意:--如果目标方法为成员方法,则第一个参数需要传调用对象。--如果目标方法为静态方法,则不需要。print(luafunc1(CallOverrideFunc,10));print(luafunc2(CallOverrideFunc,10.2));
复制代码 Lua使用C#委托事件
- print("*********Lua调用C#委托事件相关知识点*********");--Lua使用C#委托事件的语法基本上和C#中的使用是一致的。local LuaCallDelegate = CS.LuaCallDelegate();local func1 =function()print("Lua使用c#委托调用lua的方法");end--Lua中使用C#委托,将其当作成员变量来使用,使用的规则和C#中一样,先等号赋值,再+=--需要注意,lua中没有+=运算,需要我们老老实实的写A = A + B这种形式。
- LuaCallDelegate.DelegateTest = func1;--lua中使用C#委托,也可以直接添加lua函数,这种添加方法有点类似于在C#中添加匿名方法或者lambda表达式。--不建议使用,因为这种添加形式只能加不能减。
- LuaCallDelegate.DelegateTest = LuaCallDelegate.DelegateTest +function()print("lua使用C#委托添加的临时变量");end
- LuaCallDelegate.DelegateTest();--注销回调函数
- LuaCallDelegate.DelegateTest = LuaCallDelegate.DelegateTest - func1;
- LuaCallDelegate.DelegateTest();--清空委托链,相当于C#中调用 = null
- LuaCallDelegate.DelegateTest =nil;local func2 =function()print("事件添加的函数");end--在事件的添加上,lua不同于C#--事件添加函数使用对象名:事件名("+",函数名)的方式来添加--注销事件同理
- LuaCallDelegate:EventTest("+",func2);
- LuaCallDelegate:OnEventStart();--同样可以使用此方法来添加匿名函数
- LuaCallDelegate:EventTest("+",function()print("这是使用事件添加的匿名函数");end);
- LuaCallDelegate:OnEventStart();--注销事件
- LuaCallDelegate:EventTest("-",func2);
- LuaCallDelegate:OnEventStart();--由于事件不能在类外调用委托链清空,所以我们将委托链清空的方法封装在事件申明类中。
- LuaCallDelegate:ClearEvent();
- LuaCallDelegate:OnEventStart();
复制代码 Lua使用C#获得二维数组的值
- print("*********Lua调用C#二维数组相关知识点*********");--Lua使用C#的数组,并直接通过索引查找数组元素只适用于一维数组。--想要获得多维数组的元素需要使用Array基类中的一个获取元素的方法GetValue。--同理如果我们想要设置多维数组的值也可以通过方法SetValue来实现。--注意这里的GetSet都为成员方法。local Call2Array = CS.Call2Array();--获得C#2维数组的行长度print(Call2Array.My2Array:GetLength(0));--获得C#2维数组的列长度print(Call2Array.My2Array:GetLength(1));--获得C#2维数组的元素,我们需要通过GetValue方法来实现。--获得索引为(0,0)的元素print(Call2Array.My2Array:GetValue(0,0));--获得索引为(1,2)的元素print(Call2Array.My2Array:GetValue(1,2));--遍历C#二维数组for i=0,Call2Array.My2Array:GetLength(0)-1dofor j=0, Call2Array.My2Array:GetLength(1)-1doprint(Call2Array.My2Array:GetValue(i,j));endend
复制代码 Lua调用C#nil和null的比较
- print("*********Lua调用C#nil和null相关知识点*********");--首先我们需要明白:C#中的null和lua中的nil是不能判等的。--我们用一个开发中比较常见的问题来说明这个问题。--问题:判断一个游戏物体是否存在rigidbody,如果不存在需要添加一个tigidbody组件。local GameObject = CS.UnityEngine.GameObject;local Rigidbody = CS.UnityEngine.Rigidbody;local go =GameObject("添加Rigidbody");local rigi = go:GetComponent(typeof(Rigidbody));--解决方式一:使用Equalsif rigi:Equals(nil)then
- go:AddComponent(typeof(Rigidbody));end--再次判断go物体上是否有Rigidbody组件local rigi = go:GetComponent(typeof(Rigidbody));--解决方式二:在Main中或者调用Main的调用函数中书写全局判空函数并使用。--[[
- function IsNull(param)
- if param == nil or param:Equals(nil) then
- return true;
- end
- return false;
- end
- ]]ifIsNull(rigi)thenprint("123");
- go:AddComponent(typeof(Rigidbody));end--再次判断go物体上是否有Rigidbody组件local rigi = go:GetComponent(typeof(Rigidbody));--解决方式三:在C#中为Object书写判空拓展方法并使用。--[[
- [LuaCallCSharp]
- public static class NilAndNull{
- public static bool IsNull(this Object obj)
- {
- return obj == null;
- }
- }
- ]]if rigi:IsNull()thenprint("123");
- go:AddComponent(typeof(Rigidbody));end
复制代码 CSharpCallLua和LuaCallCsharp特性
使用时机:
CSharpCallLua:当我们使用C#的接口和委托接收lua代码时(CSharp为主场),我们需要为C#类提供这个特性。另外一种情况是当我们需要使用Lua调用C#的系统类型的时候,同样需要使用到该特性。
LuaCallCsharp:当我们使用Lua调用C#时(Lua为主场),我们建议所有被lua调用的类都加上这个特性。
这两个特性保证了自定义C#类和lua代码之间的调用,但我们不能通过这两个特性实现系统类型和lua代码之间的调用。
Lua使用C#系统类型
上面对于两个特性的比较已经说明了其使用时机,但是我们注意到,当我们想用lua调用Csharp中系统类型时。我们没有办法为系统类型添加特性,这时我们就需要用到xlua的特性列表。- print("*********Lua调用C#系统类型相关知识点*********");--这里我们用unity中的Slider为例local GameObject = CS.UnityEngine.GameObject;local Slider = CS.UnityEngine.UI.Slider;local go = GameObject.Find("Slider");print(go);local sliderScript = go:GetComponent(typeof(Slider));print(sliderScript);--[[
- 这里直接添加监听事件,会直接报错提示需要为UnityAction添加[CSharpCallLua]的特性。
- 但我们知道我们是不可以改变系统类型的,所以我们需要用到xlua提供的特性列表:
- [CSharpCallLua]
- public static List<Type> CSharpCallLuaList = new List<Type>()
- {
- typeof(UnityAction<float>),
- };
- [LuaCallCSharp]
- public static List<Type> LuaCallCSharpList = new List<Type>()
- {
- typeof(GameObject),
- typeof(Rigidbody),
- };
- 这两个分别为[CSharpCallLua]特性列表和[LuaCallCSharp]特性列表。
- 我们只需要在里面写我们想要添加特性的类型就可以了,之后重新生成代码,Xlua就会帮我们构建可以使用的中间代码。
- 特性列表还有一大用途就是集中添加我们需要申明特性的类,这会使我们的代码更加专业和简洁。
- 完成特性列表的书写后我们就可以通过lua来调用C#或者unity中的系统类型了。
- 需要注意:
- 特性列表和特性列表所在的类一定都为静态的。
- ]]
- sliderScript.onValueChanged:AddListener(function(value)print(value);end);
复制代码 Lua使用C#协程
- print("*********Lua调用C#协程相关知识点*********");local GameObject = CS.UnityEngine.GameObject;local WaitForSeconds = CS.UnityEngine.WaitForSeconds;--Lua调用C#的协程需要注意几点:--[[
- 1. 建议将所有用到的和C#协程有关的类都预先保存
- 2. Lua不能直接使用C#协程中的yield return
- 3. 虽然我们使用lua调用C#的StartCoroutine来开启协程,但是协程函数的书写使用Lua语法书写
- 4. lua协程不能直接传入StartCoroutine中,我们需要接用xlua为我们提供的util工具表来实现
- 5. 由于调用的是C#的协程启动和停止相关的函数,所以除过协程本身的书写,其他也还是遵循C#的规则
- ]]--加载xlua提供给我们的util工具表
- util =require("xlua.util");--首先我们先来创建一个游戏物体local go =GameObject("Coroutine");local mono = go:AddComponent(typeof(CS.CsharpCallLua.CallCoroutine));--书写lua协程
- func =function()local param =1;whiletruedo--使用lua的yield来暂停协程
- coroutine.yield(WaitForSeconds(1));print(param);
- param = param +1;--如果param大于10,我们就停止协程if param >10then
- mono:StopCoroutine(cor);endendend--使用C#的StartCoroutine开启lua协程,这里使用util工具表辅助实现
- cor = mono:StartCoroutine(util.cs_generator(func));
复制代码 Lua使用C#泛型函数
- print("*********Lua调用C#泛型相关知识点*********");local callT = CS.CallT();local chlid = CS.CallT.InnerChild();local father = CS.CallT.InnerFather();--lua仅支持有约束有参数且约束为类的泛型函数
- callT:TestFunc1(child,father);
- callT:TestFunc1(father,child);--lua不支持没有参数的泛型函数--callT:TestFunc2();--lua不支持没有约束的泛型函数--callT:TestFunc3(child);--lua不支持非class的约束--callT:TestFunc4();--补充知识:xlua为我们提供了对应的转换方法,但是慎用--[[
- 此方法的有一定的限制:
- 1. 如果我们的游戏项目是Mono打包则这种方式是完全支持的;但如果我们的项目是IL2CPP打包,则只有引用类型可以使用。
- ]]--[[
- 1. 使用get_generic_method方法得到通用函数
- xlua.get_generic_method(类, 函数名字符串);
- 2. 使用通用函数设置泛型类型
- 3. 调用设置了泛型类型的通用函数。
- ]]local testFunc3 = xlua.get_generic_method(CS.CallT,"TestFunc3");local testFunc3_R =testFunc3(CS.CallT.InnerFather);--[[
- 调用:
- 1. 成员方法:第一个参数需要穿阿如调用函数的对象。
- 2. 静态方法:不需要传调用对象。
- ]]testFunc3_R(callT, father);
复制代码 |
|