UH2S2L6——全局函数获取
本章代码关键字
1 2 3 4
| [CSharpCallLua] LuaFunction luaFunction.Call() luaFunction.Dispose()
|
全局函数的获取
-
无参无返回
- 自定义委托
- Action
- UnityAction
- LuaFunction
-
有参有返回
-
多返回
-
变长参数
先在Lua声明不同的函数(无参无返回,有参有返回,多返回值,变长参数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| TestFun = function() print("无参无返回") end
TestFun2 = function(a) print("有参有返回") return a + 1 end
TestFun3 = function(a) return 1, 2, false, "123", a end
TestFun4 = function(a, ...) print("a") arg = { ... } for key, value in pairs(arg) do print(key, value) end end
|
无参无返回值
我们可以像调用全局变量一样调用全局方法,就是需要使用委托来接收它
这个委托可以是我们自己声明的,也可以使用Unity提供的,也可以使用C#提供的,
xLua也提供了对应的变量类型接收方法,调用它需要使用Call方法(官方建议少用,因为会产生垃圾,性能不佳)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public delegate void CustomCall();
public class L5_CallFunction : MonoBehaviour { void Start() { LuaManager.Instance.Init(); LuaManager.Instance.DoLuaFile("Main");
CustomCall call = LuaManager.Instance.Global.Get<CustomCall>("TestFun"); call(); UnityAction ua = LuaManager.Instance.Global.Get<UnityAction>("TestFun"); ua(); Action action = LuaManager.Instance.Global.Get<Action>("TestFun"); action(); LuaFunction lf = LuaManager.Instance.Global.Get<LuaFunction>("TestFun"); lf.Call(); } }
|
有参有返回值
和上面的无参无返回值函数的调用大同小异,但是需要做额外的步骤
首先是委托需要有对应的参数与返回值类型,并且加上特性 [CSharpCallLua] ,
并且在工具栏点击 XLua - Clear Generate Code 选项,生成对应的C#代码,该委托才能被识别!
[CSharpCallLua]特性有不在类声明前添加也可以使用的方法,对不能直接修改代码的类也有效,详见:让系统类型和Lua能互相访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public delegate void CustomCall();
[CSharpCallLua] public delegate int CustomCall2(int a);
public class L5_CallFunction : MonoBehaviour { void Start() { LuaManager.Instance.Init(); LuaManager.Instance.DoLuaFile("Main"); CustomCall2 call2 = LuaManager.Instance.Global.Get<CustomCall2>("TestFun2"); Debug.Log("有参有返回值:" + call2(10)); } }
|

C#也自带了有参有返回值的委托Func<>,可以直接使用,泛型参数第一个一定是返回值,后面都是参数
1 2 3 4
| CustomCall2 call2 = LuaManager.Instance.Global.Get<CustomCall2>("TestFun2"); Debug.Log("有参有返回值:" + call2(10)); Func<int, int> sFun = LuaManager.Instance.Global.Get<Func<int, int>>("TestFun2"); Debug.Log("有参有返回值:" + sFun(20));
|
也可以使用XLua提供的委托,执行时需要传入参数,它会返回object[],返回值从这个数组获取
1 2
| LuaFunction lf2 = LuaManager.Instance.Global.Get<LuaFunction>("TestFun2"); Debug.Log("有参有返回值:" + lf2.Call(30)[0]);
|

多返回值
C#不支持函数多返回值,我们需要使用out和ref来接收,也就是通过传入的参数变量来接收返回值
具体声明方式是,用out修饰接收返回值参数,将接收返回值的变量传入到方法中,这些变量在这些过方法后就会接收到方法的返回值
(同样的,这种新声明出来的委托还是需要加上特性并执行Generate Code)
1 2 3 4
| [CSharpCallLua] public delegate int CustomCall3(int a, out int b, out bool c, out string d, out int e);
|
函数的第一个返回值还是通过委托本身返回出来,剩下的返回值就是通过参数传递变量来接收返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| [CSharpCallLua] public delegate int CustomCall3(int a, out int b, out bool c, out string d, out int e);
public class L5_CallFunction : MonoBehaviour { void Start() { LuaManager.Instance.Init(); LuaManager.Instance.DoLuaFile("Main"); CustomCall3 call3 = LuaManager.Instance.Global.Get<CustomCall3>("TestFun3"); int b; bool c; string d; int e; Debug.Log("第一个返回值:" + call3(100, out b, out c, out d, out e)); Debug.Log("剩余的返回值:" + b + "_" + c + "_" + d + "_" + e); } }
|

用ref修饰参数的效果是一样的,唯一的区别是,ref传入的变量必须初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| [CSharpCallLua] public delegate int CustomCall3(int a, out int b, out bool c, out string d, out int e); [CSharpCallLua] public delegate int CustomCall4(int a, ref int b, ref bool c, ref string d, ref int e);
public class L5_CallFunction : MonoBehaviour { void Start() { LuaManager.Instance.Init(); LuaManager.Instance.DoLuaFile("Main"); CustomCall3 call3 = LuaManager.Instance.Global.Get<CustomCall3>("TestFun3"); int b; bool c; string d; int e; Debug.Log("第一个返回值:" + call3(100, out b, out c, out d, out e)); Debug.Log("剩余的返回值:" + b + "_" + c + "_" + d + "_" + e);
CustomCall4 call4 = LuaManager.Instance.Global.Get<CustomCall4>("TestFun3"); int b1 = 0; bool c1 = true; string d1 = ""; int e1 = 0; Debug.Log("第一个返回值:" + call4(200, ref b1, ref c1, ref d1, ref e1)); Debug.Log("剩余的返回值:" + b1 + "_" + c1 + "_" + d1 + "_" + e1); } }
|

这里同样可以使用XLua提供的委托,执行时需要传入参数,它会返回object[],返回值从这个数组获取(少用)
1 2 3 4 5 6
| LuaFunction lf3 = LuaManager.Instance.Global.Get<LuaFunction>("TestFun3"); object[] objs = lf3.Call(1000); for (int i = 0; i < objs.Length; i++) { Debug.Log("第" + i + "个返回值是:" + objs[i]); }
|
变长参数
调用变长参数函数的委托,我们在参数列表使用C#提供的变长参数即可,
只不过和Lua相比C#的变长参数需要我们指定类型,如果类型不确定,可以使用object
如果可以确定是单一类型,就直接使用对应的类型即可
(同样的,这种新声明出来的委托还是需要加上特性并执行Generate Code)
1 2 3
| [CSharpCallLua] public delegate void CustomCall5(string a, params int[] args);
|
这里同样可以使用XLua提供的委托,执行时传入对应的参数即可(少用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| [CSharpCallLua] public delegate void CustomCall5(string a, params int[] args);
public class L5_CallFunction : MonoBehaviour { void Start() { LuaManager.Instance.Init(); LuaManager.Instance.DoLuaFile("Main");
CustomCall5 call5 = LuaManager.Instance.Global.Get<CustomCall5>("TestFun4"); call5("传入了这些参数:", 1, 2, 3, 4, 5, 666, 7, 88, 999); LuaFunction lf4 = LuaManager.Instance.Global.Get<LuaFunction>("TestFun4"); lf4.Call("传入了这些参数:", 3, 4, 54321, 6666, 7, 88, 9); } }
|
LuaFunction的销毁
当LuaFunction的调用完毕时,应当手动销毁,否则将一直占用内存,造成内存泄露,LuaTable同理
Lua解析器的tick()就是会释放我们没有手动销毁的LuaTable,LuaFunction