• [游戏开发][unity]Xlua中使用proto、json、lpeg


    Xlua支持的第三方库在链接里,请自行查看,或看下方截图

    链接里包含:lua-protobuf、lua-rapidjson、luasocket、luajit等

    https://github.com/chexiongsheng/build_xlua_with_libs/tree/master/buildhttps://github.com/chexiongsheng/build_xlua_with_libs/tree/master/build


     本文不介绍luasocket、FFI等库的使用

    C#代码引用第三方库

    在你项目初始化lua虚拟机的地方引入下方代码

    1. _luaEnv = new LuaEnv();
    2. _luaEnv.AddLoader(CustomLoaderMethod);
    3. _luaEnv.AddBuildin("rapidjson", XLua.LuaDLL.Lua.LoadRapidJson);
    4. _luaEnv.AddBuildin("lpeg", XLua.LuaDLL.Lua.LoadLpeg);
    5. _luaEnv.AddBuildin("pb", XLua.LuaDLL.Lua.LoadLuaProfobuf);

    第三方库的引用方式就上面几句代码

    如果你不想自己写Demo,可以看一下官方自己写的Unity Demo

    https://github.com/chexiongsheng/build_xlua_with_libs/tree/master/LibsTestProj

     重要提醒!!!:

    Xlua官网的Unity工程,使用第三方库无法加载!!!

    用 GitHub chengxiongsheng的Demo可以加载,我怀疑是官网Xlua Unity工程的Plugins里的dll没有生成带有第三方库的版本。

    build_xlua_with_libs/build这个源码可以使用cmake自己生成库,然后扔到Unity中使用


    Lua代码中使用第三方库

    Json和ProtoBuffer是我们开发中常见的工具,还有一个不是很常见的lpeg,找了几篇文章,大家自行跳转

    https://www.jianshu.com/p/e8e1c5abfdbbhttps://www.jianshu.com/p/e8e1c5abfdbbLPEG库简介_suzuiyue的博客-CSDN博客_lpegLPEG库简介LPEG是一个供lua使用的基于 Parsing Expression Grammars 的模式匹配库,这篇文章只是讲其如何使用,并不涉及底层如何实现。LPEG 的函数主要分为三类,第一类是创建Pattern的构造函数,第二类是 Capture 函数, 第三类则是 match 等函数。 Capture 就是指一个Pattern,当前匹配时会产生某些捕获的值。Match 等函数lpeg.https://blog.csdn.net/suzuiyue/article/details/52905372

    在lua当中如何使用这三个库呢,下面挨个介绍

    1:Json的使用

    引用rapidjson有几种方式

    1. --调用方式1,声明一个全局变量RapidJson,代码执行后,可以在其他.lua文件中直接调用RapidJson 而不需要再次require('rapidjson')
    2. RapidJson = require('rapidjson')
    3. --调用方式2,脚本内局部使用
    4. local rapidJson = require('rapidjson')
    5. --调用方式3,方法内局部使用
    6. function XXX()
    7. local rapidJson = require('rapidjson')
    8. end

    rapidjson具体使用,在调用encode和decode方法前,要先require('rapidjson')

    1. --反序列化
    2. local t = rapidjson.decode('{"a":123}')
    3. print(t.a)
    4. t.a = 456
    5. --序列化
    6. local s = rapidjson.encode(t)
    7. print('json', s)

    2:ProtoBuf的使用

    xLua官方源码:

    https://github.com/Tencent/xLua

    lua-protobuf源码:

    https://github.com/starwing/lua-protobuf


    protoc.lua文件

    protoc.lua在 https://github.com/starwing/lua-protobuf 源码里


    提示:Xlua的PB库支持proto2和proto3,需要在协议里标明是2还是3

    第一步:准备proto协议协议文件。

    使用pb的前提肯定得让lua层的pb加载协议,协议才是序列化、反序列化的前提。

    我准备了一个战斗协议,命名为Fight.proto,里面还引用了NetStruct_Fight.proto文件

    1. syntax="proto2";
    2. import "NetStruct_Fight.proto";
    3. message CSEnterBattle
    4. {
    5. optional int32 battleSid = 1; // 战役配置id
    6. optional int32 isFixedArray = 2; // 是否固定阵容0不是 1
    7. }
    8. //[返回][游戏服]进入战斗结果
    9. message SCEnterBattle
    10. {
    11. optional int64 battleId = 1; //服务器战斗序号
    12. repeated CampData camps = 2; // 战斗阵营数据 (仅站位和card_sid)
    13. }

    xlua中有两种加载proto协议文件的方式,下面分别介绍

    第一种加载proto方式:

    1、先通过ResourceManager框架加载协议文本文件,

    2、然后获取文本的string,

    3、调用 assert(pcNew:load(A,B)),其中,A变量是string,B变量是文件名带扩展名

    1. local pcNew = nil
    2. function StartLoadProto()
    3. --protoc是一个lua文件,一般是lua库里带着的此处需要引用一下
    4. protoc = require "Framework/protoc"
    5. pcNew= protoc.new()
    6. --由于我的Fight.proto里引用了另一个proto,因此先加载引用
    7. LoadProto("NetStruct_Fight")
    8. --加载完引用后,再加载proto才不会报错
    9. LoadProto("Fight")
    10. end
    11. function LoadProto(fileName)
    12. --C#资源加载器
    13. local AssetsData = CS.MoAssetText()
    14. AssetsData:Load("Battle/Proto/"..fileName..".txt")
    15. --不管你怎么加载,一定是从Unity里把协议文本取出来
    16. local protoString = AssetsData:GetText()
    17. --这一句是核心语句,协议文本加载入pb库,现在pb就知道该如何解析bytes数据啦
    18. assert(pcNew:load(protoString,fileName..".proto"))
    19. end

    CS.MoAssetText()是我们项目的文本文件加载,你可以根据自己项目选择如何加载,反正最后一定要拿到文本文件的string。


    下面开始介绍第二种加载proto方式

    1. assert(
    2. ProtocLib:load
    3. [[
    4. syntax = "proto3";
    5. message CSEnterBattle
    6. {
    7. int32 battleSid = 1; // 战役配置id
    8. int32 isFixedArray = 2; // 是否固定阵容0不是 1是
    9. }
    10. //[返回][游戏服]进入战斗结果
    11. message SCEnterBattle
    12. {
    13. int64 battleId = 1; //服务器战斗序号
    14. CampData camps = 2; // 战斗阵营数据
    15. }
    16. //阵营数据
    17. message CampData
    18. {
    19. int32 id = 1; //阵营id
    20. int32 UnitId = 2; //阵营类型
    21. }
    22. ]]
    23. )

    仔细看上面代码你会发现,其实就是把proto协议里的内容全部都写到一个lua脚本里去,这个lua脚本包括了所有引用和非引用的proto数据结构,我这里的文件叫protoDefine.lua.txt文件,我们可以写一个批处理工具,把协议全都按行写入到一个文件中。如果你的协议非常多,那么会生成一个几千行甚至几万行的lua文件。项目启动的时候,在合适的位置调用 require "Net/ProtoDefine"加载这个脚本即可把协议加载到库。

    上面介绍了两种加载proto协议的方式


    开始序列化和反序列化数据

    加载完proto协议,我们当然要使用它呀,也就是序列化和反序列化数据

    1. function UsePB()
    2. --第一步,加载bytes,请注意,EnterBattleMsg是我本地已经序列化出来的二进制数据文件测试用
    3. --将来肯定是从服务器获取二进制数据
    4. local bytes = LoadBytes("EnterBattleMsg")
    5. --反序列化,使用proto库里的SCEnterBattle结构体序列化该bytes数据
    6. local SCEnterBattleTab = assert(pb.decode('SCEnterBattle', bytes))
    7. --请注意,反序列化后得到SCEnterBattleTab,它是个table
    8. --获取数据如下
    9. print("战役Id: ".. SCEnterBattleTab.battleId)
    10. --序列化语句
    11. local bytes = pb.encode('SCEnterBattle', SCEnterBattleTab)
    12. --此时我们又得到了一个最初的bytes二进制数据
    13. print(pb.tohex(bytes))--打印数据
    14. end
    15. function LoadBytes(fileName)
    16. --C#资源加载器
    17. local AssetsData = CS.MoAssetText()
    18. --同步加载文件
    19. AssetsData:Load("Battle/Proto/"..fileName..".bytes")
    20. --不管你怎么加载,一定是从Unity里把二进制数据读出来
    21. return AssetsData:GetBytes()
    22. end

    3:lpeg的使用

     lpeg的功能非常多,建议直接去看上面分享的链接,详细看一下使用

    1. local lpeg = require "lpeg"
    2. local match = lpeg.match
    3. local P = lpeg.P
    4. -- value是string的情况
    5. local ps = P'ab'
    6. print(match(ps, "a")) ---> nil
    7. print(match(ps, "abcd")) ---> 3 注:只匹配"ab"

  • 相关阅读:
    redux一步一步的使用
    C#面:C#面向对象的思想主要包括什么?
    MindFusion Scheduler for JavaScript 2.0 Crack
    PhpSpreadsheet设置单元格常用操作汇总
    python多线程与多进程
    formData文件上传与下载,文件大小转换
    Linux内网渗透基础篇
    十七、Webpack搭建本地服务器
    2022杭电多校赛第八场
    【ocean】报错*Error* quotient: can‘t handle (nil / nil)
  • 原文地址:https://blog.csdn.net/liuyongjie1992/article/details/127089110