Unity3D學習筆記(三十二):Xlua(2)
阿新 • • 發佈:2019-02-12
使用 ceil list date action oat static arp 分享 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 luaEnvXLua支持C#函數的重載,但XLua並不是嚴格的支持C#函數的重載,因為Lua的number類型對應C#的int、float、double等類型。 XLua支持C#函數的可變參數方法,並且跟C#的調用相同。 XLua支持C#函數的默認參數 C#的默認參數必須放在非默認參數的後面,調用時,如果傳入值那麽就按照傳入的值處理,如果未傳入值,那麽就按照默認的值處理。 C#的默認參數可以有多個,但是所有默認參數需要放在所有普通參數的後面。 LuaCallCSharpFunction2.lua.txt= 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; } } }
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; } }
Unity3D學習筆記(三十二):Xlua(2)