Xlua支持通过子类对象访问父类的变量属性和方法
对于C#的ref,out参数的方法
当调用的时候:out类型的参数是不需要传递实参的,普通的参数和ref参数需要传递实参。
out,ref传出值通过lua函数的多返回值传出的,如果C#的函数有返回值,那么lua调用时的第一个返回值就是函数的返回值,之后依次是out和ref参数的传出值。
LuaCallCSharpFunction1.lua.txt
print('开始执行LuaCallCSharpFunction1.lua') --先实例化一个类对象 d = CS.Lesson.D() --1、有一个参数 d:Func1("小明") --2、有一个out类型的参数,out类型的参数不需要传递实参 --out的传出的值是通过返回值的形式传出的 rt = d:Func2() print("rt: ", rt) --3、有一个ref类型的参数 --ref修改的值也是通过返回值传出的 --ref需要传入实参 a = "lua" rt = d:Func3(a) print("a: ", a) print("rt: ", rt) --4、一个out参数,一个ref参数 --out不需要实参,所以函数值需要一个实参 --一个out一个ref,所以函数有两个返回值 a, b = d:Func4("ref") print("a: ", a) print("b: ", b) --5、函数有返回值,一个out一个ref a, b, c = d:Func5("ref") print("a: ", a) print("b: ", b) print("c: ", c) print('结束执行LuaCallCSharpFunction1.lua')
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; public class LuaCallCSharpFunction1 : MonoBehaviour { LuaEnv luaEnv = new LuaEnv(); void Start() { luaEnv.DoString("require 'LuaCallCSharpFunction1' "); } private void OnDestroy() { luaEnv.Dispose(); } } namespace Lesson { public class D { public void Func1(string a) { Debug.Log("D -- Func1:" + a); } public void Func2(out string a) { a = "Func2"; Debug.Log("D -- Func2:" + a); } public void Func3(ref string a) { Debug.Log("D -- Func3:" + a); a = "Func3"; } public void Func4(out string a, ref string b) { a = "Func4"; Debug.Log("D -- Func4:" + a + "---" + b); } public bool Func5(out string a, ref string b) { a = "Func5"; Debug.Log("D -- Func5:" + a + "---" + b); return true; } } }
XLua支持C#函数的重载,但XLua并不是严格的支持C#函数的重载,因为Lua的number类型对应C#的int、float、double等类型。
XLua支持C#函数的可变参数方法,并且跟C#的调用相同。
XLua支持C#函数的默认参数
C#的默认参数必须放在非默认参数的后面,调用时,如果传入值那么就按照传入的值处理,如果未传入值,那么就按照默认的值处理。
C#的默认参数可以有多个,但是所有默认参数需要放在所有普通参数的后面。
LuaCallCSharpFunction2.lua.txt
print('开始执行LuaCallCSharpFunction1.lua') --先实例化一个类对象 e = CS.Lesson.E() --不传入参数 e:Func1() --传入一个string类型的参数 e:Func1("小明") --传入一个number类型的参数 e:Func1(1) e:Func1(1.2) --传入两个string类型的参数 e:Func1("小明", "小红") --支持可变参数 e:Func2("1", "2", "小明") --支持默认参数 e:Func3() e:Func3(10) print('结束执行LuaCallCSharpFunction1.lua')
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; public class LuaCallCSharpFunction2 : MonoBehaviour { LuaEnv luaEnv = new LuaEnv(); // Use this for initialization void Start() { luaEnv.DoString("require 'LuaCallCSharpFunction2' "); } // Update is called once per frame void Update() { } private void OnDestroy() { luaEnv.Dispose(); } } namespace Lesson { public class E { //重载方法 public void Func1(){ Debug.Log("无参数的重载Func1");} public void Func1(string str) { Debug.Log("有string参数的重载Func1"); } public void Func1(int a) { Debug.Log("有int参数的重载Func1"); } public void Func1(float a) { Debug.Log("有float参数的重载Func1"); } public void Func1(string str1, string str2) { Debug.Log("有两个string参数的重载Func1"); } //可变参数 public void Func2(params string[] str_Arr) { foreach (var item in str_Arr) { Debug.Log("可变参数:" + item); } } //默认参数 public void Func3(string a = "小明") { Debug.Log("a: " + a); } public void Func3(int b, string a = "小明", string c = "小红") { Debug.Log("b: " + b + "a: " + a + "c: " + c); } } }
XLua调用C#枚举
CS.命名空间.枚举名.枚举值 或 CS.枚举名.枚举值
Lua把字符串或数字转换成枚举
CS.命名空间.枚举名.__CastFrom(数字或字符串) 或 CS.枚举名.__CastFrom(数字或字符串)
注意:转换无限的数字不会报错,但是转换无效的字符串会报错。
LuaCallCSharpEnum.lua.txt
print('开始执行LuaCallCSharpEnum.lua') --先实例化一个类对象 f = CS.Lesson.F() --参数是一个枚举类型 f:Func1(CS.LessonEnum.Type1.type2) --枚举与int或字符串相互转化 --自动转化 f:Func1(2) --手动转化,数字的值可以任意,超过枚举项数,不会报错,字符串必须保证值存在 f:Func1(CS.LessonEnum.Type1.__CastFrom(10)) f:Func1(CS.LessonEnum.Type1.__CastFrom('小明')) print('结束执行LuaCallCSharpEnum.lua')
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; public class LuaCallCSharpEnum : MonoBehaviour { LuaEnv luaEnv = new LuaEnv(); void Start() { luaEnv.DoString("require 'LuaCallCSharpEnum' "); } private void OnDestroy() { luaEnv.Dispose(); } } namespace Lesson { public class F { public void Func1(LessonEnum.Type1 type) { Debug.Log(type.ToString()); } } } namespace LessonEnum { public enum Type1 { type1, type2, type3, 小明, } }
Xlua是支持C#的委托,并且可以把Lua的方法添加到委托中去,但是Lua没有 += -=运算符。
对于一个空的委托,只能对其进行赋值a = b,不能a = a + b的形式添加
对于一个非空的委托,可以使用a = a + b(a = a - b)的形式去把b添加到a中
如果想把一个委托变为空。可以使用a = nil的方式
LuaCallCSharpDelegate.lua.txt
print('开始执行LuaCallCSharpDelegate.lua') --lua对一个空委托进行赋值只能使用=,不能使用 a = a + b CS.Lesson.G.del = CS.Lesson.G.Func1; --lua可以对一个非空委托使用 a = a + b 的形式,把b添加到a里去 CS.Lesson.G.del = CS.Lesson.G.del + CS.Lesson.G.Func1; --lua可以对一个非空委托使用 a = a - b 的形式,把b从到a里移除 CS.Lesson.G.del = CS.Lesson.G.del - CS.Lesson.G.Func1; func1 = function() print("这是lua的方法") end --把一个lua的方法,添加到C#的委托里 CS.Lesson.G.del = CS.Lesson.G.del + func1 --委托的调用 CS.Lesson.G.del() --非静态的委托 --先实例对象 g = CS.Lesson.G() g.del1 = func1; --把委托变为空 g.del1 = nil if g.del1 then g.del1() end print('结束执行LuaCallCSharpDelegate.lua')
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; public class LuaCallCSharpDelegate : MonoBehaviour { LuaEnv luaEnv = new LuaEnv(); // Use this for initialization void Start() { luaEnv.DoString("require 'LuaCallCSharpDelegate' "); } private void OnDestroy() { luaEnv.Dispose(); } } namespace Lesson { public class G { public delegate void Del(); public static Del del; public static void Func1() { Debug.Log("func1"); } public Del del1; } }
静态委托:CS.命名空间.类名.委托变量名 或 CS.类名.委托变量名
成员委托:对象名.委托变量名
静态事件:CS.命名空间.类名.事件名('+或-', 想要添加到事件里的方法名)
成员事件:对象名:事件名('+或-', 方法名)
报错原因:对于委托和事件,在lua虚拟机释放之前需要C#的事件或委托需要清空
print('开始执行LuaCallCSharpEvent.lua') --lua添加C#的事件的方法和C#是不一样的 --lua通过这种方式,把第二个参数添加到事件里 --静态事件:CS.命名空间.类名.事件名('+或-', 想要添加到事件里的方法名) CS.Lesson.H.staticEvent('+', CS.Lesson.H.Func1) --lua是可以把lua的方法添加到事件里去的 func1 = function() print("这是lua.func1的方法") end CS.Lesson.H.staticEvent('+', func1) --调用 CS.Lesson.H.InvokeStaticEvent() --成员的事件 --实例化对象 h = CS.Lesson.H() --成员事件与静态事件的调用方式不一样 --成员事件:对象名:事件名('+或-', 方法名) func2 = function() print("这是lua.func2的方法") end h:unStaticEvent('+', func2) --添加C#里的成员事件 func3 = function() h:Func2() end h:unStaticEvent('+', func3) --调用 h:InvokeUnStaticEvent() --清空C#事件里的方法 CS.Lesson.H.staticEvent('-', CS.Lesson.H.Func1) CS.Lesson.H.staticEvent('-', func1) h:unStaticEvent('-', func2) h:unStaticEvent('-', func3) print('结束执行LuaCallCSharpEvent.lua')
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; public class LuaCallCSharpEvent : MonoBehaviour { LuaEnv luaEnv = new LuaEnv(); void Start () { luaEnv.DoString("require 'LuaCallCSharpEvent' "); } private void OnDestroy() { luaEnv.Dispose(); } } namespace Lesson { public class H { public delegate void Del(); public static event Del staticEvent; public static void Func1() { Debug.Log("H Func1"); } public static void InvokeStaticEvent() { if (staticEvent != null) { staticEvent(); } } public event Del unStaticEvent; public void Func2() { Debug.Log("H Func2"); } public void InvokeUnStaticEvent() { if (unStaticEvent != null) { unStaticEvent(); } } } }
UI案例
print('开始执行UI.lua') Set = function(Self) uiLua = Self end Awake = function() --获取Button组件,typeof(CS.UnityEngine.UI.Button)获取Button类型 button = uiLua.transform:Find("Button"):GetComponent(typeof(CS.UnityEngine.UI.Button)); --把lua的方法添加到button的事件中去 button.onClick:AddListener(ClickButton); --获取Text组件 text = uiLua.transform:Find("Text"):GetComponent(typeof(CS.UnityEngine.UI.Text)); --获取Slider组件 slider = uiLua.transform:Find("Slider"):GetComponent(typeof(CS.UnityEngine.UI.Slider)); --给Slider添加事件 slider.onValueChanged:AddListener(SliderValueChanged); --获取Image组件 image = uiLua.transform:Find("Image"):GetComponent(typeof(CS.UnityEngine.UI.Image)); end Destroy = function() --把事件移除 button.onClick:RemoveListener(ClickButton); button.onClick:Invoke()--删除瞬间,机器无法判断,需执行一次Invoke() slider.onValueChanged:RemoveListener(SliderValueChanged); slider.onValueChanged:Invoke() end ClickButton = function() text.text = "你好呀" end SliderValueChanged = function(value) image.color = CS.UnityEngine.Color(value, 0, 0); end print('结束执行UI.lua')
在Editor里添加AddCSharpCallLua类,给系统的UnityAction类添加[XLua.CSharpCallLua]特性
using System.Collections; using System.Collections.Generic; using UnityEngine; public static class AddCSharpCallLua { [XLua.CSharpCallLua] public static List<System.Type> list = new List<System.Type>() { typeof(UnityEngine.Events.UnityAction<float>), typeof(GameObject) }; }
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; using UnityEngine.UI; public class UILua : MonoBehaviour { private LuaEnv luaEnv = new LuaEnv(); [CSharpCallLua] private delegate void Del(UILua ui); private Del set; [CSharpCallLua] private delegate void Del1(); private Del1 awake; private Del1 destroy; // Use this for initialization void Awake() { luaEnv.DoString("require 'UI' "); set = luaEnv.Global.Get<Del>("Set"); set(this); awake = luaEnv.Global.Get<Del1>("Awake"); if (awake != null) { awake(); } destroy = luaEnv.Global.Get<Del1>("Destroy"); } // Update is called once per frame void OnDestroy() { if (destroy != null) { destroy(); } //虚拟机释放之前所有的委托映射的方法,全部设为null set = null; awake = null; destroy = null; luaEnv.Dispose(); } }
案列-MVC界面
MVC.lua.txt
print("开始执行MVC") Set = function(Self) panel = Self end Awake = function() --print("Awake") skill1Button = panel.transform:Find("Buttons/Skill1Button"):GetComponent(typeof(CS.UnityEngine.UI.Button)); skill2Button = panel.transform:Find("Buttons/Skill2Button"):GetComponent(typeof(CS.UnityEngine.UI.Button)); hpText = panel.transform:Find("Hand/HPSlider/Text"):GetComponent(typeof(CS.UnityEngine.UI.Text)); hpSlider = panel.transform:Find("Hand/HPSlider"):GetComponent(typeof(CS.UnityEngine.UI.Slider)); skill1Button.onClick:AddListener(Skill1Click); skill2Button.onClick:AddListener(Skill2Click); --当数据改变时,需要更新界面,把更新界面的方法添加到PlayerData的事件里去 CS.PlayerData.Instance:updateEvent('+', UpdatePanel); end Start = function() --更新界面显示 UpdatePanel() end Destroy = function() --print("Destroy") CS.PlayerData.Instance:updateEvent('-', UpdatePanel); skill1Button.onClick:RemoveListener(Skill1Click); skill1Button.onClick:Invoke() skill2Button.onClick:RemoveListener(Skill2Click); skill2Button.onClick:Invoke() end UpdatePanel = function() hpSlider.normalizedValue = CS.PlayerData.Instance.CurrentHP / CS.PlayerData.Instance.MaxHP; hpText.text = CS.PlayerData.Instance.CurrentIntHP .. "/" .. CS.PlayerData.Instance.MaxIntHP; end Skill1Click = function() --print("Skill1Click"); CS.PlayerController.Instance:AddHPByGold(100); end Skill2Click = function() --print("Skill2Click"); CS.PlayerController.Instance:Hit(100, CallBack); end CallBack = function(str) print("CallBack: ", str) end
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; public class PanelLua : MonoBehaviour { private LuaEnv luaenv = new LuaEnv(); [CSharpCallLua] private delegate void Del(PanelLua ui); private Del set; [CSharpCallLua] private delegate void Del1(); private Del1 awake; private Del1 destroy; private Del1 start; // Use this for initialization void Awake () { luaenv.DoString("require 'MVC'"); set = luaenv.Global.Get<Del>("Set"); set(this); awake = luaenv.Global.Get<Del1>("Awake"); if (awake != null) { awake(); } start = luaenv.Global.Get<Del1>("Start"); destroy = luaenv.Global.Get<Del1>("Destroy"); } private void Start() { if (start != null) { start(); } } private void OnDestroy() { if (destroy != null) { destroy(); } //虚拟机释放之前所有的委托映射的方法,全部为null set = null; awake = null; destroy = null; start = null; luaenv.Dispose(); } }
Lua里面没有强制转化,Math.Ceil()向上取整也无法得到整数,可以使用如下方法在C#中返回整数
public float CurrentHP { get { return currentHP; } set { if (currentHP != value) { currentHP = value; UpdatePanel(); } } } public int CurrentIntHP { get { return (int)currentHP; } }