Unity3D学习笔记(三十二):Xlua(2)

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

猜你喜欢

转载自www.cnblogs.com/ciaowoo/p/10363713.html