015-热更新之xlua语言二

Posted jake-caiee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了015-热更新之xlua语言二相关的知识,希望对你有一定的参考价值。

因为我们在前面已经花了大量的时间来学习lua,所以我们在本节就会结束xlua的部分。

2.3更轻量的by value方式:映射到dictionary<>,list<>。不想定义class或者interface的话,我们可以考虑用这个,前提table下key和value的类型都是一致的。

Dictionary<string, object> dict = luaenv.Global.Get<Dictionary<string, object>>("person");
        foreach (string key in dict.Keys)
        {
            print(key + "-" + dict[key]);
        }

这个就是通过dictionary的方式来完成的,不过它有一个注意点是它只能输出有键值对的table,其他的形式它是映射不出来的。那么我们应该如果去解决这个问题呢?这里就要用到的是list<>了,但是这个集合也有一个要注意的是它只能映射数组类型的table,所以我们需要将两者相结合来使用,下面是list的代码:

List<object> listTxt = luaenv.Global.Get<List<object>>("person");
        foreach (object o in listTxt)
        {
            print(o);
        }

2.4另外一种方式 by ref方式:映射到luatable类 这种方式的好处也不需要生成代码,但也有一点问题,比较慢。我们不建议使用这种方式,建议使用第二种方式。其实这种方式是插件帮我们写好的,我们只需要直接调用就行了,代码如下:

 LuaTable tab = luaenv.Global.Get<LuaTable>("person");
        print(tab.Get<string>("name"));

这四种方式我们已经全部介绍了一遍,我们发现其实他们用的都是同一个方法luaenv.Golbal.Get<T>("name")的形式,这也就说明了xlua的方便性,我们只需要简单的创建xlua虚拟机就行了,这样大大的节约了时间,加快代码的效率。

三、访问一个全局的function

我们现在发现xlua只用一个Get,但是不同的是类型映射。

1.映射到delegate 

这种方式是建议的方式,性能好很多,而且类型安全。缺点是要生成代码。在这里首先要回顾一下delegate,因为在现在这个阶段我用的比较少,所以有点忘记了,有必要再去看看。

c#中的委托(delegate)类似c或c++中函数的指针。委托(delegate)是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托(delegate)特别用于实现事件和回调函数。所有的委托(delegate)都派生自system.delegate类。上面说delegate可以理解成指针。我们把delegate实例化出来后,就可以给里面传递一个方法,这样就是间接的引用了,所以我们写下如下的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 委托
{
    delegate int NumberChanger(int n);
    class Program
    {
        static int num = 10;
        public static int AddNum(int p)
        {
            num += p;
            return num;
        }
        public static int MultNum(int q)
        {
            num *= q;
            return q;
        }
        public static int GetNum()
        {
            return num;
        }
        static void Main(string[] args)
        {
            //创建委托实例
            NumberChanger nc1 = new NumberChanger(AddNum);
            NumberChanger nc2 = new NumberChanger(MultNum);

            //使用委托对象调用方法
            nc1(25);
            Console.WriteLine("Value of Num:{0}", GetNum());
            nc2(25);
            Console.WriteLine("value of Num:{0}", GetNum());
            Console.ReadKey();
        }
    }
}

nc1(24)虽然是给委托赋值的,但是nc1是引用AddNum()这个方法的,委托会调用这个方法,这实际上就是一种引用。经过我们这样的梳理,我们就不会对委托产生迷茫了。好了我们继续刚才的话题。

在这里我们有一个问题,如果lua中的函数有返回值怎么办呢?lua中是可以返回多个返回值的,而c#只能返回一个返回值,我们看下面的代码:

  Add add = luaenv.Global.Get<Add>("method");
        int resa;int resb;
        int res=add(34, 67,out resa,out resb);
        print(res+"   "+resa + "   " + resb);
        add = null;
        luaenv.Dispose();
    }
    [CSharpCallLua]
    delegate int Add(int a, int b,out int resa,out int resb);

使用out就行了,我们就能解决返回值不一致的问题。效果如下:

技术分享图片

2.映射到LuaFunction这种凡是的优缺点刚好和第一种相反。使用也简单,LuaFunction上有个变参的call函数,可以传递任意类型,任意个数的参数,返回值是object的数组,对应于lua的多返回值。

 LuaFunction func = luaenv.Global.Get<LuaFunction>("method");
        object[] os = func.Call(1, 2);
        foreach (object o in os)
        {
            print(o);
        }

 

Lua调用从C#

本部分也是比较简单的。我们只说两个部分。废话不多说,我们就向下看吧。

1.new C#对象

我们创建一个txt文件LuaCallCSharp.lua.txt 在里面写CS.UnityEngine.GameObject()  在C#中我们写

LuaEnv luaenv = new LuaEnv();
luaenv.DoString("require ‘LuaCallCSharp‘");
luaenv.Dispose();

这样就会在unity中创建一个gameobject了。

2.Lua访问c#中成员属性和方法

local gameObject=CS.UnityEngine.GameObject
local camera=gameObject.Find("Main Camera")
camera.name="666"
local Cam01=camera:GetComponent("Camera")
gameObject.Destroy(Cam01)

这样写的效果就是将unity中的Main Camera的名字改成666,并将Main Camera身上的Camera给禁用掉。这样就能完成lua对c#的访问。好了,所有的xlua内容今天全部完成了,我们在下一节的时候,将会用xlua开发一个案例,一起学习吧。



以上是关于015-热更新之xlua语言二的主要内容,如果未能解决你的问题,请参考以下文章

xLua热更新实现热更新

Unity2020 几种常用热更新方案的优劣及XLua实战

XLua----热更新

Xlua热更新

游戏热更新实战案例(基于xLua)

[Unity XLua]热更新XLua入门-俄罗斯方块实例篇