zoukankan      html  css  js  c++  java
  • 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;
        }
    }
  • 相关阅读:
    jsp 说明标签
    atcoder 它February 29th
    centos编译内核:no space left on device 解
    《Javascript权威指南》十六学习笔记:BOM资源---BOM基本应用
    2014ACM/ICPC亚洲区域赛牡丹江站汇总
    Swift_3_功能
    ExtJs在disabled和readOnly美学分析
    android -- 蓝牙 bluetooth (四)OPP文件传输
    android -- 蓝牙 bluetooth (三)搜索蓝牙
    android -- 蓝牙 bluetooth (二) 打开蓝牙
  • 原文地址:https://www.cnblogs.com/vuciao/p/10363713.html
Copyright © 2011-2022 走看看