zoukankan      html  css  js  c++  java
  • xLua 学习

    xLua  https://github.com/Tencent/xLua

    文档  https://tencent.github.io/xLua/public/v1/guide/index.html

    FAQ  https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/faq.md

    Features  https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/features.md

    教程  https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/XLua%E6%95%99%E7%A8%8B.md

    Tutorial

    using UnityEngine;
    using System.Collections;
    using XLua;
    
    namespace Tutorial
    {
        public class ByString : MonoBehaviour
        {
            LuaEnv luaenv = null;
            // Use this for initialization
            void Start()
            {
                luaenv = new LuaEnv();
                luaenv.DoString("print('hello world')");
            }
    
            // Update is called once per frame
            void Update()
            {
                if (luaenv != null)
                {
                    luaenv.Tick();
                }
            }
    
            void OnDestroy()
            {
                luaenv.Dispose();
            }
        }
    }
    LoadLuaScriptByString
    Resources/byfile.lua.txt
    
    namespace Tutorial
    {
        public class ByFile : MonoBehaviour
        {
            LuaEnv luaenv = null;
            // Use this for initialization
            void Start()
            {
                luaenv = new LuaEnv();
                luaenv.DoString("require 'byfile'");
            }
    
            // Update is called once per frame
            void Update()
            {
                if (luaenv != null)
                {
                    luaenv.Tick();
                }
            }
    
            void OnDestroy()
            {
                luaenv.Dispose();
            }
        }
    }
    LoadLuaScriptByFile
    using UnityEngine;
    using System.Collections;
    using XLua;
    
    namespace Tutorial
    {
        public class CustomLoader : MonoBehaviour
        {
            LuaEnv luaenv = null;
            // Use this for initialization
            void Start()
            {
                luaenv = new LuaEnv();
                luaenv.AddLoader((ref string filename) =>
                {
                    if (filename == "InMemory")
                    {
                        string script = "return {ccc = 9999}";
                        return System.Text.Encoding.UTF8.GetBytes(script);
                    }
                    return null;
                });
                luaenv.DoString("print('InMemory.ccc=', require('InMemory').ccc)");
            }
    
            // Update is called once per frame
            void Update()
            {
                if (luaenv != null)
                {
                    luaenv.Tick();
                }
            }
    
            void OnDestroy()
            {
                luaenv.Dispose();
            }
        }
    }
    LoadLuaScriptLoader
    using UnityEngine;
    using System.Collections.Generic;
    using System;
    using XLua;
    
    public class CSCallLua: MonoBehaviour {
    
        LuaEnv luaEnv = null;
    
        string script = @"
            a = 1
            b = 'hello world'
            c = true
    
            d = {
                f1 = 12,
                f2 = 34,
                1,2,3,
                add = function(self, a, b)
                    print('d.add called')
                    return a + b
                end
            }
    
            function e()
                print('i am e')
            end
    
            function f(a, b)
                print('a', a, 'b', b)
                return 1, { f1 = 1024 }
            end
    
            function ret_e()
                print('ret_e called')
                return e
            end
        ";
    
        public class DClass {
            public int f1;
            public int f2;
        }
    
        [CSharpCallLua]
        public interface ItfD {
            int f1 { get; set; }
            int f2 { get; set; }
            int add(int a, int b);
        }
    
        [CSharpCallLua]
        public delegate int FDelegate(int a, string b, out DClass c);
    
        [CSharpCallLua]
        public delegate Action GetE();
    
    
        void Start() {
            luaEnv = new LuaEnv();
            luaEnv.DoString(script);
    
            Debug.Log("_G.a = " + luaEnv.Global.Get<int>("a"));
            Debug.Log("_G.b = " + luaEnv.Global.Get<string>("b"));
            Debug.Log("_G.c = " + luaEnv.Global.Get<bool>("c"));
    
            DClass d = luaEnv.Global.Get<DClass>("d");  // 映射到有对应字段的class, by value
            Debug.Log("_G.d = { f1 = " + d.f1 + ", f2 = " + d.f2 + " }");
    
            Dictionary<string, double> d1 = luaEnv.Global.Get<Dictionary<string, double>>("d"); // 映射到Dictionary<string, double>, by value
            Debug.Log("_G.d = { f1 = " + d1["f1"] + ", f2 = " + d1["f2"] + "}, d.Count = " + d1.Count);
    
            List<double> d2 = luaEnv.Global.Get<List<double>>("d"); // 映射到List<double>, by value
            Debug.Log("_G.d.len = " + d2.Count);
    
            ItfD d3 = luaEnv.Global.Get<ItfD>("d"); // 映射到interface实例,by ref, 这个要求interface加到生成列表,否则会返回null,建议用法
            d3.f2 = 1000;
            Debug.Log("_G.d= { f1 = " + d3.f1 + ", f2 = " + d3.f2 + "}");
            Debug.Log("_G.d:add(1, 2) = " + d3.add(1, 2));
    
            LuaTable d4 = luaEnv.Global.Get<LuaTable>("d"); // 映射到一个delegate, 要求delegate加到生成列表,否则返回null,建议用法
            Debug.Log("_G.d = { f1 = " + d4.Get<int>("f1") + ", f2 = " + d4.Get<int>("f2") + "}");
    
            Action e = luaEnv.Global.Get<Action>("e");  // 映射到一个delegate,要求delegate加到生成列表,否则返回null, 建议用法
            e();
    
            FDelegate f = luaEnv.Global.Get<FDelegate>("f");
            DClass d_ret;
            int f_ret = f(100, "john", out d_ret);  // lua的多返回值映射: 从左往右映射到c#的输出参数,输出参数包括返回值,out参数,ref参数
            Debug.Log("ret.d = { f1 = " + d_ret.f1 + ", f2 = " + d_ret.f2 + "}, ret = " + f_ret);
    
            GetE ret_e = luaEnv.Global.Get<GetE>("ret_e");  // delegate可以返回更复杂的类型,甚至是另外一个delegate
            e = ret_e();
            e();
    
            LuaFunction d_e = luaEnv.Global.Get<LuaFunction>("e");
            d_e.Call();
        }
    
        void Update() {
            if (luaEnv != null) {
                luaEnv.Tick();
            }    
        }
    
        void OnDestroy() {
            luaEnv.Dispose();   
        }
    }
    CSharpCallLua
    using UnityEngine;
    using System;
    using XLua;
    
    
    [LuaCallCSharp]
    public class BaseClass {
    
        public static int BSF = 1;
    
        public int BMF { get; set; }
    
        public static void BSFunc() {
            Debug.Log("Derived Static Func, BSF = " + BSF);
        }
    
        public void BMFunc() {
            Debug.Log("Derived Member Func, BMF = " + BMF);
        }
    }
    
    public struct Param1 {
        public int x;
        public string y;
    }
    
    [LuaCallCSharp]
    public enum TestEnum {
        E1,
        E2
    }
    
    [LuaCallCSharp]
    public class DerivedClass: BaseClass {
    
        [LuaCallCSharp]
        public enum TestEnumInner {
            E3,
            E4
        }
    
        public void DMFunc() {
            Debug.Log("Derived Member Func, DMF = " + DMF);
        }
    
        public int DMF { get; set; }
    
        public double ComplexFunc(Param1 p1, ref int p2, out string p3, Action luafunc, out Action csfunc) {
            Debug.Log("P1 = { x = " + p1.x + ", y = " + p1.y + "},p2 = " + p2);
    
            luafunc();
            p2 = p2 * p1.x;
            p3 = "hello " + p1.y;
    
            csfunc = () => {
                Debug.Log("csharp callback invoked!");
            };
    
            return 1.23;
        }
    
        public void TestFunc(int i) {
            Debug.Log("TestFunc(int i)");
        }
    
        public void TestFunc(string i) {
            Debug.Log("TestFunc(string i)");
        }
    
        public static DerivedClass operator+(DerivedClass a, DerivedClass b) {
            DerivedClass ret = new DerivedClass();
            ret.DMF = a.DMF + b.DMF;
            return ret;
        }
    
        public void DefaultValueFunc(int a = 100, string b = "cccc", string c = null) {
            UnityEngine.Debug.Log("DefaultValueFunc: a = " + a + ", b = " + b + ", c = " + c);
        }
    
        public void VariableParamsFunc(int a, params string[] strs) {
            UnityEngine.Debug.Log("VariableParamsFunc: a = " + a);
            foreach (var str in strs) {
                UnityEngine.Debug.Log("str:" + str);
            }
        }
    
        public TestEnum EnumTestFunc(TestEnum e) {
            Debug.Log("EnumTestFunc: e = " + e);
            return TestEnum.E2;
        }
    
        public Action<string> TestDelegate = (param) => {
            Debug.Log("TestDelegate in C#:" + param);
        };
    
        public event Action TestEvent;
    
        public void CallEvent() {
            TestEvent();
        }
    
        public ulong TestLong(long n) {
            return (ulong)(n + 1);
        }
    
        class InnerCalc: ICalc {
            public int add(int a, int b) {
                return a + b;
            }
    
            public int id = 100;
        }
    
        public ICalc GetCalc() {
            return new InnerCalc();
        }
    
        public void GenericMethod<T>() {
            Debug.Log("GenericMethod<" + typeof(T) +">");
        }
    }
    
    
    [LuaCallCSharp]
    public interface ICalc {
        int add(int a, int b);
    }
    
    [LuaCallCSharp]
    public static class DerivedClassExtensions {
        public static int GetSomeData(this DerivedClass obj) {
            Debug.Log("GetSomeData ret = " + obj.DMF);
            return obj.DMF;
        }
    
        public static int GetSomeBaseData(this BaseClass obj) {
            Debug.Log("GetSomeBaseData ret = " + obj.BMF);
            return obj.BMF;
        }
    
        public static void GenericMethodOfString(this DerivedClass obj) {
            obj.GenericMethod<string>();
        }
    }
    
    
    public class LuaCallCs1 : MonoBehaviour {
    
        LuaEnv luaEnv = null;
        string script = @"
            function demo()
                --new C#对象
                local newGameObj = CS.UnityEngine.GameObject()
                local newGameObj2 = CS.UnityEngine.GameObject('helloworld')
                print(newGameObj, newGameObj2)
            
                --访问静态属性,方法
                local GameObject = CS.UnityEngine.GameObject
                print('UnityEngine.Time.deltaTime:', CS.UnityEngine.Time.deltaTime) --读静态属性
                CS.UnityEngine.Time.timeScale = 0.5 --写静态属性
                print('helloworld', GameObject.Find('helloworld')) --静态方法调用
    
                --访问成员属性,方法
                local DerivedClass = CS.DerivedClass
                local testobj = DerivedClass()
                testobj.DMF = 1024--设置成员属性
                print(testobj.DMF)--读取成员属性
                testobj:DMFunc()--成员方法
    
                --基类属性,方法
                print(DerivedClass.BSF)--读基类静态属性
                DerivedClass.BSF = 2048--写基类静态属性
                DerivedClass.BSFunc();--基类静态方法
                print(testobj.BMF)--读基类成员属性
                testobj.BMF = 4096--写基类成员属性
                testobj:BMFunc()--基类方法调用
    
                --复杂方法调用
                local ret, p2, p3, csfunc = testobj:ComplexFunc({x=3, y = 'john'}, 100, function()
                   print('i am lua callback')
                end)
                print('ComplexFunc ret:', ret, p2, p3, csfunc)
                csfunc()
    
                --重载方法调用
                testobj:TestFunc(100)
                testobj:TestFunc('hello')
    
                --操作符
                local testobj2 = DerivedClass()
                testobj2.DMF = 2048
                print('(testobj + testobj2).DMF = ', (testobj + testobj2).DMF)
    
                --默认值
                testobj:DefaultValueFunc(1)
                testobj:DefaultValueFunc(3, 'hello', 'john')
    
                --可变参数
                testobj:VariableParamsFunc(5, 'hello', 'john')
    
                --Extension methods
                print(testobj:GetSomeData()) 
                print(testobj:GetSomeBaseData()) --访问基类的Extension methods
                testobj:GenericMethodOfString()  --通过Extension methods实现访问泛化方法
    
                --枚举类型
                local e = testobj:EnumTestFunc(CS.TestEnum.E1)
                print(e, e == CS.TestEnum.E2)
                print(CS.TestEnum.__CastFrom(1), CS.TestEnum.__CastFrom('E1'))
                print(CS.DerivedClass.TestEnumInner.E3)
                assert(CS.BaseClass.TestEnumInner == nil)
    
                --Delegate
                testobj.TestDelegate('hello') --直接调用
                local function lua_delegate(str)
                    print('TestDelegate in lua:', str)
                end
                testobj.TestDelegate = lua_delegate + testobj.TestDelegate --combine,这里演示的是C#delegate作为右值,左值也支持
                testobj.TestDelegate('hello')
                testobj.TestDelegate = testobj.TestDelegate - lua_delegate --remove
                testobj.TestDelegate('hello')
    
                --事件
                local function lua_event_callback1() print('lua_event_callback1') end
                local function lua_event_callback2() print('lua_event_callback2') end
                testobj:TestEvent('+', lua_event_callback1)
                testobj:CallEvent()
                testobj:TestEvent('+', lua_event_callback2)
                testobj:CallEvent()
                testobj:TestEvent('-', lua_event_callback1)
                testobj:CallEvent()
                testobj:TestEvent('-', lua_event_callback2)
    
                --64位支持
                local l = testobj:TestLong(11)
                print(type(l), l, l + 100, 10000 + l)
    
                --typeof
                newGameObj:AddComponent(typeof(CS.UnityEngine.ParticleSystem))
    
                --cast
                local calc = testobj:GetCalc()
                print('assess instance of InnerCalc via reflection', calc:add(1, 2))
                assert(calc.id == 100)
                cast(calc, typeof(CS.ICalc))
                print('cast to interface ICalc', calc:add(1, 2))
                assert(calc.id == nil)
           end
    
           demo()
    
           --协程下使用
           local co = coroutine.create(function()
               print('------------------------------------------------------')
               demo()
           end)
           assert(coroutine.resume(co))
        ";
    
    
        void Start() {
            luaEnv = new LuaEnv();
            luaEnv.DoString(script);
        }
    
        void Update() {
            if (luaEnv != null) {
                luaEnv.Tick();
            }
        }
    
        void OnDestroy() {
            luaEnv.Dispose();
        }
    }
    LuaCallCs

    Examples

    using UnityEngine;
    using XLua;
    
    
    public class Helloworld : MonoBehaviour
    {
        // Use this for initialization
        void Start()
        {
            LuaEnv luaenv = new LuaEnv();
            luaenv.DoString("CS.UnityEngine.Debug.Log('hello world')");
            luaenv.Dispose();
        }
    
        // Update is called once per frame
        void Update()
        {
    
        }
    }
    01_HelloWorld 快速入门的例子
    LuaTestScript.lua.txt
    
    local speed = 10
    local lightCpnt = nil
    
    function start()
        print("lua start...")
        print("injected object", lightObject)
        lightCpnt = lightObject:GetComponent(typeof(CS.UnityEngine.Light))
    end
    
    function update()
        local r = CS.UnityEngine.Vector3.up * CS.UnityEngine.Time.deltaTime * speed
        self.transform:Rotate(r)
        lightCpnt.color = CS.UnityEngine.Color(CS.UnityEngine.Mathf.Sin(CS.UnityEngine.Time.time) / 2 + 0.5, 0, 0, 1)
    end
    
    function ondestroy()
        print("lua destory")
    end
    
    LuaBehaviour.cs
    
    using UnityEngine;
    using XLua;
    using System;
    
    [System.Serializable]
    public class Injection {
        public string name;
        public GameObject value;
    }
    
    [LuaCallCSharp]
    public class LuaBehaviour : MonoBehaviour {
    
        public TextAsset luaScript;
        public Injection[] injections;
    
        internal static LuaEnv luaEnv = new LuaEnv();   // all lua behaviour shared one luaenv only!
        internal static float lastGCTime = 0;
        internal const float GCInterval = 1;    //1 second
    
        private Action luaStart;
        private Action luaUpdate;
        private Action luaOnDestroy;
    
        private LuaTable scriptEnv;
    
        void Awake() {
            scriptEnv = luaEnv.NewTable();
    
            // 为每个脚本设置一个独立的环境,可一定程度上防止脚本间全局变量,函数冲突
            LuaTable meta = luaEnv.NewTable();
            meta.Set("__index", luaEnv.Global);
            scriptEnv.SetMetaTable(meta);
            meta.Dispose();
    
            scriptEnv.Set("self", this);
            foreach (var injection in injections) {
                scriptEnv.Set(injection.name, injection.value);
            }
    
            luaEnv.DoString(luaScript.text, "LuaTestScript", scriptEnv);
    
            Action luaAwake = scriptEnv.Get<Action>("awake");
            scriptEnv.Get("start", out luaStart);
            scriptEnv.Get("update", out luaUpdate);
            scriptEnv.Get("ondestroy", out luaOnDestroy);
    
            if (luaAwake != null) {
                luaAwake();
            }
        }
    
        void Start() {
            if (luaStart != null) {
                luaStart();
            }    
        }
    
        void Update() {
            if (luaUpdate != null) {
                luaUpdate();
            }
    
            if (Time.time - LuaBehaviour.lastGCTime > GCInterval) {
                luaEnv.Tick();
                LuaBehaviour.lastGCTime = Time.time;
            }
    
        }
    
    
        void OnDestroy() {
            if (luaOnDestroy != null) {
                luaOnDestroy();
            }
    
            luaOnDestroy = null;
            luaUpdate = null;
            luaStart = null;
            scriptEnv.Dispose();
            injections = null;
        }
    }
    02_U3DScripting 怎么用lua来写MonoBehaviour
    ButtonInteraction.lua.txt
    
    function start()
        print("lua start...")
    
        self:GetComponent("Button").onClick:AddListener(function()
            print("clicked, you input is '" ..input:GetComponent("InputField").text .."'")
        end)
    end
    
    LuaBehaviour.cs
    
    using UnityEngine;
    using XLua;
    using System;
    
    [System.Serializable]
    public class Injection
    {
        public string name;
        public GameObject value;
    }
    
    [LuaCallCSharp]
    public class LuaBehaviour : MonoBehaviour
    {
        public TextAsset luaScript;
        public Injection[] injections;
    
        internal static LuaEnv luaEnv = new LuaEnv(); //all lua behaviour shared one luaenv only!
        internal static float lastGCTime = 0;
        internal const float GCInterval = 1;//1 second 
    
        private Action luaStart;
        private Action luaUpdate;
        private Action luaOnDestroy;
    
        private LuaTable scriptEnv;
    
        void Awake()
        {
            scriptEnv = luaEnv.NewTable();
    
            // 为每个脚本设置一个独立的环境,可一定程度上防止脚本间全局变量、函数冲突
            LuaTable meta = luaEnv.NewTable();
            meta.Set("__index", luaEnv.Global);
            scriptEnv.SetMetaTable(meta);
            meta.Dispose();
    
            scriptEnv.Set("self", this);
            foreach (var injection in injections)
            {
                scriptEnv.Set(injection.name, injection.value);
            }
    
            luaEnv.DoString(luaScript.text, "LuaTestScript", scriptEnv);
    
            Action luaAwake = scriptEnv.Get<Action>("awake");
            scriptEnv.Get("start", out luaStart);
            scriptEnv.Get("update", out luaUpdate);
            scriptEnv.Get("ondestroy", out luaOnDestroy);
    
            if (luaAwake != null)
            {
                luaAwake();
            }
        }
    
        // Use this for initialization
        void Start()
        {
            if (luaStart != null)
            {
                luaStart();
            }
        }
    
        // Update is called once per frame
        void Update()
        {
            if (luaUpdate != null)
            {
                luaUpdate();
            }
            if (Time.time - LuaBehaviour.lastGCTime > GCInterval)
            {
                luaEnv.Tick();
                LuaBehaviour.lastGCTime = Time.time;
            }
        }
    
        void OnDestroy()
        {
            if (luaOnDestroy != null)
            {
                luaOnDestroy();
            }
            luaOnDestroy = null;
            luaUpdate = null;
            luaStart = null;
            scriptEnv.Dispose();
            injections = null;
        }
    }
    03_UIEvent 怎么用UI来写UI逻辑
    /*
     * Tencent is pleased to support the open source community by making xLua available.
     * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
     * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
     * http://opensource.org/licenses/MIT
     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
    */
    
    using System;
    using UnityEngine;
    using XLua;
    
    namespace XLuaTest
    {
        public class PropertyChangedEventArgs : EventArgs
        {
            public string name;
            public object value;
        }
    
        public class InvokeLua : MonoBehaviour
        {
            [CSharpCallLua]
            public interface ICalc
            {
                event EventHandler<PropertyChangedEventArgs> PropertyChanged;
    
                int Add(int a, int b);
                int Mult { get; set; }
    
                object this[int index] { get; set; }
            }
    
            [CSharpCallLua]
            public delegate ICalc CalcNew(int mult, params string[] args);
    
            private string script = @"
                    local calc_mt = {
                        __index = {
                            Add = function(self, a, b)
                                return (a + b) * self.Mult
                            end,
                            
                            get_Item = function(self, index)
                                return self.list[index + 1]
                            end,
    
                            set_Item = function(self, index, value)
                                self.list[index + 1] = value
                                self:notify({name = index, value = value})
                            end,
                            
                            add_PropertyChanged = function(self, delegate)
                                if self.notifylist == nil then
                                    self.notifylist = {}
                                end
                                table.insert(self.notifylist, delegate)
                                print('add',delegate)
                            end,
                                                    
                            remove_PropertyChanged = function(self, delegate)
                                for i=1, #self.notifylist do
                                    if CS.System.Object.Equals(self.notifylist[i], delegate) then
                                        table.remove(self.notifylist, i)
                                        break
                                    end
                                end
                                print('remove', delegate)
                            end,
    
                            notify = function(self, evt)
                                if self.notifylist ~= nil then
                                    for i=1, #self.notifylist do
                                        self.notifylist[i](self, evt)
                                    end
                                end    
                            end,
                        }
                    }
    
                    Calc = {
                        New = function (mult, ...)
                            print(...)
                            return setmetatable({Mult = mult, list = {'aaaa','bbbb','cccc'}}, calc_mt)
                        end
                    }
                ";
            // Use this for initialization
            void Start()
            {
                LuaEnv luaenv = new LuaEnv();
                Test(luaenv);//调用了带可变参数的delegate,函数结束都不会释放delegate,即使置空并调用GC
                luaenv.Dispose();
            }
    
            void Test(LuaEnv luaenv)
            {
                luaenv.DoString(script);
                CalcNew calc_new = luaenv.Global.GetInPath<CalcNew>("Calc.New");
                ICalc calc = calc_new(10, "hi", "john"); //constructor
                Debug.Log("sum(*10) =" + calc.Add(1, 2));
                calc.Mult = 100;
                Debug.Log("sum(*100)=" + calc.Add(1, 2));
    
                Debug.Log("list[0]=" + calc[0]);
                Debug.Log("list[1]=" + calc[1]);
    
                calc.PropertyChanged += Notify;
                calc[1] = "dddd";
                Debug.Log("list[1]=" + calc[1]);
    
                calc.PropertyChanged -= Notify;
    
                calc[1] = "eeee";
                Debug.Log("list[1]=" + calc[1]);
            }
    
            void Notify(object sender, PropertyChangedEventArgs e)
            {
                Debug.Log(string.Format("{0} has property changed {1}={2}", sender, e.name, e.value));
            }
    
            // Update is called once per frame
            void Update()
            {
    
            }
        }
    }
    04_LuaObjectOrented: lua面向对象和C#的配合
    using UnityEngine;
    using System;
    using XLua;
    
    namespace XLuaTest
    {
        [GCOptimize]
        [LuaCallCSharp]
        public struct Pedding
        {
            public byte c;
        }
    
        [GCOptimize]
        [LuaCallCSharp]
        public struct MyStruct
        {
            public MyStruct(int p1, int p2)
            {
                a = p1;
                b = p2;
                c = p2;
                e.c = (byte)p1;
            }
            public int a;
            public int b;
            public decimal c;
            public Pedding e;
        }
    
        [LuaCallCSharp]
        public enum MyEnum
        {
            E1,
            E2
        }
    
        [CSharpCallLua]
        public delegate int IntParam(int p);
    
        [CSharpCallLua]
        public delegate Vector3 Vector3Param(Vector3 p);
    
        [CSharpCallLua]
        public delegate MyStruct CustomValueTypeParam(MyStruct p);
    
        [CSharpCallLua]
        public delegate MyEnum EnumParam(MyEnum p);
    
        [CSharpCallLua]
        public delegate decimal DecimalParam(decimal p);
    
        [CSharpCallLua]
        public delegate void ArrayAccess(Array arr);
    
        [CSharpCallLua]
        public interface IExchanger
        {
            void exchange(Array arr);
        }
    
        [LuaCallCSharp]
        public class NoGc : MonoBehaviour
        {
            LuaEnv luaenv = new LuaEnv();
    
            IntParam f1;
            Vector3Param f2;
            CustomValueTypeParam f3;
            EnumParam f4;
            DecimalParam f5;
    
            ArrayAccess farr;
            Action flua;
            IExchanger ie;
            LuaFunction add;
    
            [NonSerialized]
            public double[] a1 = new double[] { 1, 2 };
            [NonSerialized]
            public Vector3[] a2 = new Vector3[] { new Vector3(1, 2, 3), new Vector3(4, 5, 6) };
            [NonSerialized]
            public MyStruct[] a3 = new MyStruct[] { new MyStruct(1, 2), new MyStruct(3, 4) };
            [NonSerialized]
            public MyEnum[] a4 = new MyEnum[] { MyEnum.E1, MyEnum.E2 };
            [NonSerialized]
            public decimal[] a5 = new decimal[] { 1.00001M, 2.00002M };
    
            public float FloatParamMethod(float p)
            {
                return p;
            }
    
            public Vector3 Vector3ParamMethod(Vector3 p)
            {
                return p;
            }
    
            public MyStruct StructParamMethod(MyStruct p)
            {
                return p;
            }
    
            public MyEnum EnumParamMethod(MyEnum p)
            {
                return p;
            }
    
            public decimal DecimalParamMethod(decimal p)
            {
                return p;
            }
    
            // Use this for initialization
            void Start()
            {
                luaenv.DoString(@"
                    function id(...)
                        return ...
                    end
    
                    function add(a, b) return a + b end
                
                    function array_exchange(arr)
                        arr[0], arr[1] = arr[1], arr[0]
                    end
    
                    local v3 = CS.UnityEngine.Vector3(7, 8, 9)
                    local vt = CS.XLuaTest.MyStruct(5, 6)
    
                    function lua_access_csharp()
                        monoBehaviour:FloatParamMethod(123) --primitive
                        monoBehaviour:Vector3ParamMethod(v3) --vector3
                        local rnd = math.random(1, 100)
                        local r = monoBehaviour:Vector3ParamMethod({x = 1, y = 2, z = rnd}) --vector3
                        assert(r.x == 1 and r.y == 2 and r.z == rnd)
                        monoBehaviour:StructParamMethod(vt) --custom struct
                        r = monoBehaviour:StructParamMethod({a = 1, b = rnd, e = {c = rnd}})
                        assert(r.b == rnd and r.e.c == rnd)
                        monoBehaviour:EnumParamMethod(CS.XLuaTest.MyEnum.E2) --enum
                        monoBehaviour:DecimalParamMethod(monoBehaviour.a5[0])
                        monoBehaviour.a1[0], monoBehaviour.a1[1] = monoBehaviour.a1[1], monoBehaviour.a1[0] -- field
                    end
    
                    exchanger = {
                        exchange = function(self, arr)
                            array_exchange(arr)
                        end
                    }
    
                    A = { B = { C = 789}}
                    GDATA = 1234;
                ");
    
                luaenv.Global.Set("monoBehaviour", this);
    
                luaenv.Global.Get("id", out f1);
                luaenv.Global.Get("id", out f2);
                luaenv.Global.Get("id", out f3);
                luaenv.Global.Get("id", out f4);
                luaenv.Global.Get("id", out f5);
    
                luaenv.Global.Get("array_exchange", out farr);
                luaenv.Global.Get("lua_access_csharp", out flua);
                luaenv.Global.Get("exchanger", out ie);
                luaenv.Global.Get("add", out add);
    
                luaenv.Global.Set("g_int", 123);
                luaenv.Global.Set(123, 456);
                int i;
                luaenv.Global.Get("g_int", out i);
                Debug.Log("g_int:" + i);
                luaenv.Global.Get(123, out i);
                Debug.Log("123:" + i);
            }
    
    
            // Update is called once per frame
            void Update()
            {
                // c# call lua function with value type but no gc (using delegate)
                f1(1); // primitive type
                f2(new Vector3(1, 2, 3)); // vector3
                MyStruct mystruct1 = new MyStruct(5, 6);
                f3(mystruct1); // custom complex value type
                f4(MyEnum.E1); //enum
                decimal dec1 = -32132143143100109.00010001010M;
                f5(dec1); //decimal
    
                // using LuaFunction.Func<T1, T2, TResult>
                add.Func<int, int, int>(34, 56); // LuaFunction.Func<T1, T2, TResult>
    
                // lua access c# value type array no gc
                farr(a1); //primitive value type array
                farr(a2); //vector3 array
                farr(a3); //custom struct array
                farr(a4); //enum arry
                farr(a5); //decimal arry
    
                // lua call c# no gc with value type
                flua();
    
                //c# call lua using interface
                ie.exchange(a2);
    
                //no gc LuaTable use
                luaenv.Global.Set("g_int", 456);
                int i;
                luaenv.Global.Get("g_int", out i);
    
                luaenv.Global.Set(123.0001, mystruct1);
                MyStruct mystruct2;
                luaenv.Global.Get(123.0001, out mystruct2);
    
                decimal dec2 = 0.0000001M;
                luaenv.Global.Set((byte)12, dec1);
                luaenv.Global.Get((byte)12, out dec2);
    
                int gdata = luaenv.Global.Get<int>("GDATA");
                luaenv.Global.SetInPath("GDATA", gdata + 1);
    
                int abc = luaenv.Global.GetInPath<int>("A.B.C");
                luaenv.Global.SetInPath("A.B.C", abc + 1);
    
                luaenv.Tick();
            }
    
            void OnDestroy()
            {
                f1 =  null;
                f2 = null;
                f3 = null;
                f4 = null;
                f5 = null;
                farr = null;
                flua = null;
                ie = null;
                add = null;
                luaenv.Dispose();
            }
        }
    }
    05_NoGc: 怎么去避免值类型的GC
    CoroutineTest.cs
    
    using UnityEngine;
    using XLua;
    
    namespace XLuaTest
    {
        public class CoroutineTest : MonoBehaviour
        {
            LuaEnv luaenv = null;
            // Use this for initialization
            void Start()
            {
                luaenv = new LuaEnv();
                luaenv.DoString("require 'coruntine_test'");
            }
    
            // Update is called once per frame
            void Update()
            {
                if (luaenv != null)
                {
                    luaenv.Tick();
                }
            }
    
            void OnDestroy()
            {
                luaenv.Dispose();
            }
        }
    }
    
    
    coruntine_test.lua
    
    local cs_coroutine = (require 'cs_coroutine')
    
    local a = cs_coroutine.start(function()
        print('coroutine a started')
    
        coroutine.yield(cs_coroutine.start(function() 
            print('coroutine b stated inside cotoutine a')
            coroutine.yield(CS.UnityEngine.WaitForSeconds(1))
            print('i am coroutine b')
        end))
        print('coroutine b finish')
    
        while true do
            coroutine.yield(CS.UnityEngine.WaitForSeconds(1))
            print('i am coroutine a')
        end
    end)
    
    cs_coroutine.start(function()
        print('stop coroutine a after 5 seconds')
        coroutine.yield(CS.UnityEngine.WaitForSeconds(5))
        cs_coroutine.stop(a)
        print('coroutine a stoped')
    end)
    
    cs_coroutine.lua
    
    local util = require 'xlua.util'
    
    local gameobject = CS.UnityEngine.GameObject('Coroutine_Runner')
    CS.UnityEngine.Object.DontDestroyOnLoad(gameobject)
    local cs_coroutine_runner = gameobject:AddComponent(typeof(CS.XLuaTest.Coroutine_Runner))
    
    return {
        start = function(...)
            return cs_coroutine_runner:StartCoroutine(util.cs_generator(...))
        end;
    
        stop = function(coroutine)
            cs_coroutine_runner:StopCoroutine(coroutine)
        end
    }
    
    Coroutine_Runner.cs
    
    using UnityEngine;
    using XLua;
    using System.Collections.Generic;
    using System.Collections;
    using System;
    
    namespace XLuaTest
    {
        public class Coroutine_Runner : MonoBehaviour
        {
        }
    
    
        public static class CoroutineConfig
        {
            [LuaCallCSharp]
            public static List<Type> LuaCallCSharp
            {
                get
                {
                    return new List<Type>()
                {
                    typeof(WaitForSeconds),
                    typeof(WWW)
                };
                }
            }
        }
    }
    06_Coroutine: lua协程怎么和Unity协程相配合

    相关文章

    腾讯开源手游热更新方案:Unity3D下的XLua方案介绍

  • 相关阅读:
    【407训练】第一周总结
    [Ural1306] Sequence Median(网上很多题解骗人,这才是对的!业界良心!)
    拓扑排序
    前端知识——Django
    前端知识——jQuery、前端插件、web框架、Django
    前端知识——DOM、jQuery
    前端知识——HTML、CSS
    python整理-day13
    python整理-day12
    python整理-day11
  • 原文地址:https://www.cnblogs.com/revoid/p/11280348.html
Copyright © 2011-2022 走看看