Unity3d腾讯手游热更新方案Xlua编程

上次简单写了下XLua自定义Load

本文接着上一篇文章内容全面介绍Unity3d下的XLua编程

加载Lua

using System.Collections;
using System.Text;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class LoadLua : MonoBehaviour
{
    //创建XLUA虚拟机(最好创建一个虚拟机,多的话容易耗费性能)
    private LuaEnv luaEnv;
	
	void Start ()
    {
        luaEnv = new LuaEnv();

        //读取lua内容
        luaEnv.DoString("print('HelloWord!')");

        //读取lua文件(文件内容是lua脚本)
        //其实require是调用一个个Loader(优先加载自定义Loader)
        //有一个Loader加载成功将不再停止加载
        //以下require执行的Loader是在Resources文件夹读取并执行Loader.lua
        luaEnv.DoString("require 'LoadLua'");

        //自定义Loader
        luaEnv.AddLoader((ref string str) => {
            Debug.Log("自定义Loader参数为:" + str);
            return Encoding.UTF8.GetBytes("return 'HelloLoader!'");
        });
        luaEnv.DoString("print ( require '参数')");
    }
	
	void Update ()
    {
        if (luaEnv != null)
        {
            luaEnv.Tick();
        }
	}

    private void OnDestroy()
    {
        //释放
        luaEnv.Dispose();
    }
}


C#调用Lua

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class CSharpCallLua : MonoBehaviour
{
    private LuaEnv luaEnv;

    private class Table
    {
        public int table_intiger { get; set; }
    }

    [CSharpCallLua]
    private interface ITable
    {
        int table_intiger { get; set; }
        int fun(object a);
    }

	void Start ()
    {
        luaEnv = new LuaEnv();
        luaEnv.DoString("require('CSharpCallLua')");

        //获取类型值
        int intiger = luaEnv.Global.Get<int>("intiger");
        string str = luaEnv.Global.Get<string>("str");
        bool boolean = luaEnv.Global.Get<bool>("boolean");

        Debug.Log("取得类型:" + intiger.ToString() + " " + str + " " + boolean.ToString());

        //获取表
        //类映射
        Table tableClass = luaEnv.Global.Get<Table>("table");
        Debug.Log("通过类获取:"+tableClass.table_intiger);
        //Dictionary映射
        Dictionary<string, object> tableDict = luaEnv.Global.Get<Dictionary<string, object>>("table");
        Debug.Log("通过Dictionary容器获取:" + tableDict["table_intiger"]);
        //List映射
        List<int> tableList = luaEnv.Global.Get<List<int>>("table");
        Debug.Log("通过List容器获取:" + tableList.Count);
        //LuaTable映射
        LuaTable luaTable = luaEnv.Global.Get<LuaTable>("table");
        Debug.Log("通过LuaTable获取:" + luaTable.Get<int>("table_intiger"));
        //接口映射(注:该方法需要加上CSharpCallLua标签)
        ITable iTable = luaEnv.Global.Get<ITable>("table");
        Debug.Log("通过接口获取:" + iTable.table_intiger);
        Debug.Log("通过接口获取的函数返回值:" + iTable.fun(20));
    }

    void Update ()
    { 
        if(luaEnv!=null)
        {
            luaEnv.Tick();
        }
	}

    private void OnDestroy()
    {
        if (luaEnv != null)
        {
            luaEnv.Dispose();
        }
    }
}


Lua调用C#

using UnityEngine;
using System.Collections;
using System;
using XLua;
using System.Collections.Generic;

namespace Tutorial
{
    [LuaCallCSharp]
    public class BaseClass
    {
        public static void BSFunc()
        {
            Debug.Log("Driven Static Func, BSF = "+ BSF);
        }

        public static int BSF = 1;

        public void BMFunc()
        {
            Debug.Log("Driven Member Func, BMF = " + BMF);
        }

        public int BMF { get; set; }
    }

    public struct Param1
    {
        public int x;
        public string y;
    }

    [LuaCallCSharp]
    public enum TestEnum
    {
        E1,
        E2
    }

    [LuaCallCSharp]
    public class DrivenClass : BaseClass
    {
        [LuaCallCSharp]
        public enum TestEnumInner
        {
            E3,
            E4
        }

        public void DMFunc()
        {
            Debug.Log("Driven 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 DrivenClass operator +(DrivenClass a, DrivenClass b)
        {
            DrivenClass ret = new DrivenClass();
            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 : Calc
        {
            public int add(int a, int b)
            {
                return a + b;
            }

            public int id = 100;
        }

        public Calc GetCalc()
        {
            return new InnerCalc();
        }

        public void GenericMethod<T>()
        {
            Debug.Log("GenericMethod<" + typeof(T) + ">");
        }
    }

    [LuaCallCSharp]
    public interface Calc
    {
        int add(int a, int b);
    }

    [LuaCallCSharp]
    public static class DrivenClassExtensions
    {
        public static int GetSomeData(this DrivenClass 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 DrivenClass obj)
        {
            obj.GenericMethod<string>();
        }
    }
}

public class LuaCallCs : 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 DrivenClass = CS.Tutorial.DrivenClass
            local testobj = DrivenClass()
            testobj.DMF = 1024--设置成员属性
            print(testobj.DMF)--读取成员属性
            testobj:DMFunc()--成员方法

            --基类属性,方法
            print(DrivenClass.BSF)--读基类静态属性
            DrivenClass.BSF = 2048--写基类静态属性
            DrivenClass.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 = DrivenClass()
           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.Tutorial.TestEnum.E1)
           print(e, e == CS.Tutorial.TestEnum.E2)
           print(CS.Tutorial.TestEnum.__CastFrom(1), CS.Tutorial.TestEnum.__CastFrom('E1'))
           print(CS.Tutorial.DrivenClass.TestEnumInner.E3)
           assert(CS.Tutorial.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()
           calc:add(1, 2)
           assert(calc.id == 100)
           cast(calc, typeof(CS.Tutorial.Calc))
           calc:add(1, 2)
           assert(calc.id == nil)
       end

       demo()

       --协程下使用
       local co = coroutine.create(function()
           print('------------------------------------------------------')
           demo()
       end)
       assert(coroutine.resume(co))
    ";

    // Use this for initialization
    void Start ()
    {
        luaenv = new LuaEnv();
        luaenv.DoString(script);
    }
	
	// Update is called once per frame
	void Update () {
        if (luaenv != null)
        {
            luaenv.Tick();
        }
    }

    void OnDestroy()
    {
        luaenv.Dispose();
    }
}


原文地址:blog.liujunliang.com.cn

猜你喜欢

转载自blog.csdn.net/qq_33747722/article/details/78479228