1. 程式人生 > >Unity3D學習筆記(三十二):Xlua(2)

Unity3D學習筆記(三十二):Xlua(2)

使用 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 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;
    }
}

Unity3D學習筆記(三十二):Xlua(2)