美文网首页Unity程序员Unity
将xls转成protobuf供Unity使用的流程

将xls转成protobuf供Unity使用的流程

作者: DonaldW | 来源:发表于2014-06-25 15:22 被阅读7710次

    2016更新:本文写于2014。其中值得注意的是,建议默认使用python编写脚本,对跨平台有好处。而并非下文即将提及的、还不那么好地,使用bat、shell来编写。

    通用流程图

    流程图

    通用流程图简述

    1. 在python运行时下,依赖proto组件、xlrd的组件,使用xls_deploy_tool.py处理Hello.xls,生成Hello.data数据文件、及其对应的Hello.proto解释类。
    2. 在windows系统下,使用protoc.exe,将proto解释类转成中间格式Hello.desc。
    3. 将中间格式Hello.desc用语言工具翻译成其他语言解释类比如c#解释类Hello.cs。
    4. 游戏运行时引入protobuf的dll,使用c#解释类对data数据文件进行读取。

    Killer项目使用步骤

    目录解释
    • 配置软件安装目录:KillerTool\DataConfigSetup。
    • 配置表及工具目录:KillerProject\DataConfigBuild:
      • 配置表目录:KillerProject\DataConfigBuild\DataConfig。所有xls都在这里。它们是从策划SVN库里的DataConfig外链到这里的
    • 导出数据目录:KillerProject\Assets\StreamingAssets\DataConfig
    • 导出代码目录:KillerProject\Assets\Scripts\Killer\DataConfig\ProtoGen
    环境准备步骤
    • 进入配置软件安装目录:KillerTool\DataConfigSetup
    • 如果你的本地电脑没安装python及其组件
      • 视乎你是32位还是64位操作系统,安装python-2.7.7.32.msi或python-2.7.7.amd64.msi。
      • 把你刚刚选择安装python的路径添加到本地环境变量的path中。如下图 环境变量path
      • 命令行进入目录setuptools-5.1,执行命令python setup.py install
      • 命令行进入protobuf-2.5.0\python目录,执行命令python setup.py install
      • 命令行进入xlrd-0.9.3目录,执行命令python setup.py install

    环境准备步骤到此结束。

    使用方法
    • 如果你(一般是策划同学或程序同学)是修改已有xls文件,修改保存xls后,运行xls_all.bat,并上传导出数据目录里受到修改的data文件
    • 如果你(一般是程序同学)是要添加新xls文件
      • 在配置表目录添加你的xls文件(注意xls文件头格式需要符合格式
      • 修改xlsc_all.bat,新增一行call xlsc.bat <表格文件名> <表格名>,比如call xlsc.bat gm GM_CONF
      • 修改后运行xlsc_all.bat
      • 上传导出数据目录里新增的data文件
      • 上传导出代码目录里新增的cs文件
      • 修改导出代码目录里的DataConfigManager.cs文件,使用cs文件对对应的data文件进行读取。方法可参考那里已有的代码。
    • 如果你(一般是程序同学)要删除已有xls文件
      • 请删除xlsc_all.bat中对应的脚本代码
      • 请删除导出数据目录里对应的data文件
      • 请删除导出代码目录里对应的cs文件和DataConfigManager.cs里对应的解释代码

    通用项目准备步骤

    如果你准备搭建新的项目环境,或者对环境准备的方法感兴趣,可继续阅读下面的通用项目准备步骤。

    1. 准备xls_deploy_tool.py工具环境。xls_deploy_tool.py是一个python脚本,运行在python环境,并且python要安装了proto组件和xlrd组件
      • 安装python运行时
        • python官网下载并安装python2.7(不能装最新的python3,因为python3不向下兼容,而protobuff是用python2的)。
        • 把你刚刚选择安装python的路径添加到本地环境变量的path中。如下图 环境变量path
      • 安装setuptool
        • python安装protobuff之前,需要先安装setuptool。setuptool类似于python的一个组件安装管理器
        • setuptool官网的最下面点击下载安装文件,这里我们可以安装setuptools-5.1.zip。解压它。
        • 用命令行进入刚解压的setuptool目录,执行命令python setup.py install
      • 安装protobuff
        • 我们目前使用2.5.0的protobuff版本
        • protobuff官网下载protobuff的“全文件压缩包”(protobuf-2.5.0.tar.bz2)和“编译器压缩包”(protoc-2.5.0-win32.zip)
        • 将“全文件压缩包”解压
        • 在里面创建compiler文件夹,即protobuf-2.5.0\python\google\protobuf\compiler
        • 将“编译器压缩包”里的protoc.exe拷到protobuf-2.5.0\src
        • 用命令行进入刚解压的protobuf\python目录,执行命令python setup.py install
      • 安装xlrd(xls reader)
        • xlrd官网下载并解压
        • 用命令行进入刚解压的xlrd目录,执行命令python setup.py install
    2. xls_deploy_tool.py
      • xls_deploy_tool.py是腾讯魔方工作室jameyli同学的作品
      • 使用方法是在命令行键入如下命令
        • python xls_deploy_tool.py <表格名> <xls文件名>
      • 它将“符合格式”的xls文件生成data文件和proto文件
      • “符合格式”指的是要求xls的每一列的前4行用于定义数据格式。例子如图:
        • 详细格式文档可参考xls_deploy_tool.py 的文件注释。
    3. xls_deploy_tool.py生成的文件
      • 生成的data文件是最终在游戏内进行读取的数据文件,以protobuff定义的格式进行压缩存储(或者明文存储,但xls_deploy_tool.py暂时只实现了压缩存储)
      • 生成的proto文件是用于解释上面这个data文件的解释类。
        • 但由于我们需要在我们游戏内对其进行读取,而游戏往往只能运行其他高级语言,所以需要将proto翻译成对应的语言
        • 这里以C#为例
    4. 将proto语言翻译成C#语言
      • 需要分两步走:
        • 使用“编译器压缩包”(比如protoc-2.5.0-win32.zip)的protoc.exe将proto解释成“FileDescriptorSet ”中间格式
        • 使用protobuf-net的protogen.exe将“FileDescriptorSet ”翻译成cs文件
      • protoc.exe
        • 使用先前“编译器压缩包”(protoc-2.5.0-win32.zip)里的protoc.exe,命令行命令大概是
      • protogen.exe
        • 下载、解压protobuf-net
        • ProtoGen目录都需要用到,其中的protogen.exe负责将proto文件翻译成cs代码。
    5. 在Unity读取data文件,并且用cs代码解释
      • protobuf-net的github网站,下载工程的zip包,解压,把里面的protobuf-net文件夹放置在Unity工程的Assets\Plugins目录下

    注:不能使用protobuf-net\Full\unity\下的protobuf-net.dll拷到Unity工程的Assets\Plugins目录下的方法。
    因为部署到iOS设备,会发生JIT错误(ExecutionEngineException: Attempting to JIT compile method)。原因是因为iOS不允许JIT(Just In Time),只允许AOT(Ahead Of Time)。
    解决这个问题的方法之一是使用protobuf-net的precompile工具,但研究发现,过程会比较麻烦。具体可参阅precompile的help命令,或者谷歌“precompile protobuf net”。
    解决这个问题的方法之二,也是比较简单、证明过可行的,就是直接把源代码代替protobuf-net.dll,拷到Unity工程的Assets\Plugins目录下。
    由于编译protobuf-net代码需要unsafe编译,所以还需要在Assets文件夹放入“smcs.rsp”文件,里面加入一行-unsafe作为编译参数。
    - 引用导出的cs类,using ProtoBuf的命名空间,使用Serailizer.Deserialize<T>()全局函数,进行数据的解释,关键代码如下

    private T ReadOneDataConfig<T>(string FileName)
    {
        FileStream fileStream;
        fileStream = GetDataFileStream(FileName);
        if (null != fileStream)
        {
            T t = Serializer.Deserialize<T>(fileStream);
            fileStream.Close();
            return t;
        }
    
        return default(T);
    }
    private FileStream GetDataFileStream(string fileName)
    {
        string filePath = GetDataConfigPath(fileName);
        if (File.Exists(filePath))
        {
            FileStream fileStream = new FileStream(filePath, FileMode.Open);
            return fileStream;
        }
    
        return null;
    }
    private string GetDataConfigPath(string fileName)
    {
        return Application.streamingAssetsPath + "/DataConfig/" + fileName + ".data";
    }
    

    附Killer的bat文件

    @echo off
    
    set XLS_NAME=%1
    set SHEET_NAME=%2
    set DATA_DEST=%3
    
    
    
    echo.
    echo =========Compilation of %XLS_NAME%.xls=========
    
    
    ::---------------------------------------------------
    ::第一步,将xls经过xls_deploy_tool转成data和proto
    ::---------------------------------------------------
    set STEP1_XLS2PROTO_PATH=step1_xls2proto
    
    @echo on
    cd %STEP1_XLS2PROTO_PATH%
    
    @echo off
    echo TRY TO DELETE TEMP FILES:
    del *_pb2.py
    del *_pb2.pyc
    del *.proto
    del *.data
    del *.log
    del *.txt
    
    @echo on
    python xls_deploy_tool.py %SHEET_NAME% ..\DataConfig\%XLS_NAME%.xls
    
    
    
    ::---------------------------------------------------
    ::第二步:把proto翻译成cs
    ::---------------------------------------------------
    cd ..
    
    set STEP2_PROTO2CS_PATH=.\step2_proto2cs
    set PROTO_DESC=proto.protodesc
    set SRC_OUT=..\src
    
    cd %STEP2_PROTO2CS_PATH%
    
    @echo off
    echo TRY TO DELETE TEMP FILES:
    del *.cs
    del *.protodesc
    del *.txt
    
    
    @echo on
    dir ..\%STEP1_XLS2PROTO_PATH%\*.proto /b  > protolist.txt
    
    @echo on
    for /f "delims=." %%i in (protolist.txt) do protoc --descriptor_set_out=%PROTO_DESC% --proto_path=..\%STEP1_XLS2PROTO_PATH% ..\%STEP1_XLS2PROTO_PATH%\*.proto
    for /f "delims=." %%i in (protolist.txt) do ProtoGen\protogen -i:%PROTO_DESC% -o:%%i.cs
    
    
    cd ..
    
    ::---------------------------------------------------
    ::第三步:将data和cs拷到Assets里
    ::---------------------------------------------------
    
    @echo off
    set OUT_PATH=..\Assets
    set DATA_DEST=StreamingAssets\DataConfig
    set CS_DEST=Scripts\Killer\DataConfig\ProtoGen
    
    
    @echo on
    copy %STEP1_XLS2PROTO_PATH%\*.data %OUT_PATH%\%DATA_DEST%
    copy %STEP2_PROTO2CS_PATH%\*.cs %OUT_PATH%\%CS_DEST%
    
    ::---------------------------------------------------
    ::第四步:清除中间文件
    ::---------------------------------------------------
    @echo off
    echo TRY TO DELETE TEMP FILES:
    cd %STEP1_XLS2PROTO_PATH%
    del *_pb2.py
    del *_pb2.pyc
    del *.proto
    del *.data
    del *.log
    del *.txt
    cd ..
    cd %STEP2_PROTO2CS_PATH%
    del *.cs
    del *.protodesc
    del *.txt
    cd ..
    
    ::---------------------------------------------------
    ::第五步:结束
    ::---------------------------------------------------
    cd ..
    
    @echo on
    

    附protoc.exe的参数文档:

    E:\Project\ied_kl_rep\client_proj\trunk\KillerProject\DataConfigBuild\step2_prot
    o2cs>protoc --help
    Usage: protoc [OPTION] PROTO_FILES
    Parse PROTO_FILES and generate output based on the options given:
      -IPATH, --proto_path=PATH   Specify the directory in which to search for
                                  imports.  May be specified multiple times;
                                  directories will be searched in order.  If not
                                  given, the current working directory is used.
      --version                   Show version info and exit.
      -h, --help                  Show this text and exit.
      --encode=MESSAGE_TYPE       Read a text-format message of the given type
                                  from standard input and write it in binary
                                  to standard output.  The message type must
                                  be defined in PROTO_FILES or their imports.
      --decode=MESSAGE_TYPE       Read a binary message of the given type from
                                  standard input and write it in text format
                                  to standard output.  The message type must
                                  be defined in PROTO_FILES or their imports.
      --decode_raw                Read an arbitrary protocol message from
                                  standard input and write the raw tag/value
                                  pairs in text format to standard output.  No
                                  PROTO_FILES should be given when using this
                                  flag.
      -oFILE,                     Writes a FileDescriptorSet (a protocol buffer,
        --descriptor_set_out=FILE defined in descriptor.proto) containing all of
                                  the input files to FILE.
      --include_imports           When using --descriptor_set_out, also include
                                  all dependencies of the input files in the
                                  set, so that the set is self-contained.
      --include_source_info       When using --descriptor_set_out, do not strip
                                  SourceCodeInfo from the FileDescriptorProto.
                                  This results in vastly larger descriptors that
                                  include information about the original
                                  location of each decl in the source file as
                                  well as surrounding comments.
      --error_format=FORMAT       Set the format in which to print errors.
                                  FORMAT may be 'gcc' (the default) or 'msvs'
                                  (Microsoft Visual Studio format).
      --plugin=EXECUTABLE         Specifies a plugin executable to use.
                                  Normally, protoc searches the PATH for
                                  plugins, but you may specify additional
                                  executables not in the path using this flag.
                                  Additionally, EXECUTABLE may be of the form
                                  NAME=PATH, in which case the given plugin name
                                  is mapped to the given executable even if
                                  the executable's own name differs.
      --cpp_out=OUT_DIR           Generate C++ header and source.
      --java_out=OUT_DIR          Generate Java source file.
      --python_out=OUT_DIR        Generate Python source file.
    

    附protogen.exe参数列表

    E:\Project\ied_kl_rep\client_proj\trunk\KillerProject\DataConfigBuild\step2_prot
    o2cs\ProtoGen>protogen.exe --help
    protobuf-net:protogen - code generator for .proto
    usage: protogen -i:{infile2} [-i:{infile2}] [-o:{outfile}] [-t:{template}] [-p:{
    prop}[=value]] [-q] [-d]
    
    -i: Input file(s); proto definitions, either as text or pre-compiled binary (via
     protoc)
    -o: Output file; if none specified, writes to stdout
    -t: Template to use; defaults to csharp
    -p: Property for the template; value defaults to true; use -p:help to view avail
    able options
    -q: Quiet; suppresses header
    -d: Include all dependencies of the input files in the set so the set is self-co
    ntained.
    -ns: Default namespace; used in code generation when no package is specified
    
    Examples:
    
    protogen -i:input.proto -o:output.cs
    protogen -i:input.proto -o:output.xml -t:xml
    protogen -i:input.proto -o:output.cs -p:datacontract -q
    protogen -i:input.proto -o:output.cs -p:observable=true
    

    相关文章

      网友评论

      • 0ce0cf7aa088:还有啊,在通用流程图中您提到:
        2.在windows系统下,使用protoc.exe,将proto解释类转成中间格式Hello.desc。
        3.将中间格式Hello.desc用语言工具翻译成其他语言解释类比如c#解释类Hello.cs。
        为什么要将Proto解释称中间格式Hello.desc呢?Proto-net不是可以直接将Hello.proto转换成Hello.cs么?
      • 0ce0cf7aa088:您好,DonaldW,请问你生成的Data文件是什么样子的,是个二进制文件吗?你能贴出该文件的一小段让我们看看吗?
      • JumboWu:以下是在Unity3D中,读取*.data文件Log:
        ProtoException: Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see http://stackoverflow.com/q/2152978/23354
        ProtoBuf.ProtoReader.ReadUInt32 () (at Assets/Plugins/protobuf-net/ProtoReader.cs:217)
        ProtoBuf.Serializers.UInt32Serializer.Read (System.Object value, ProtoBuf.ProtoReader source) (at Assets/Plugins/protobuf-net/Serializers/UInt32Serializer.cs:35)
        ProtoBuf.Serializers.TagDecorator.Read (System.Object value, ProtoBuf.ProtoReader source) (at Assets/Plugins/protobuf-net/Serializers/TagDecorator.cs:80)
        ProtoBuf.Serializers.PropertyDecorator.Read (System.Object value, ProtoBuf.ProtoReader source) (at Assets/Plugins/protobuf-net/Serializers/PropertyDecorator.cs:77)
        ProtoBuf.Serializers.TypeSerializer.Read (System.Object value, ProtoBuf.ProtoReader source) (at Assets/Plugins/protobuf-net/Serializers/TypeSerializer.cs:227)
        ProtoBuf.Meta.RuntimeTypeModel.Deserialize (Int32 key, System.Object value, ProtoBuf.ProtoReader source) (at Assets/Plugins/protobuf-net/Meta/RuntimeTypeModel.cs:792)
        ProtoBuf.Meta.TypeModel.DeserializeCore (ProtoBuf.ProtoReader reader, System.Type type, System.Object value, Boolean noAutoCreate) (at Assets/Plugins/protobuf-net/Meta/TypeModel.cs:711)
        ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream source, System.Object value, System.Type type, ProtoBuf.SerializationContext context) (at Assets/Plugins/protobuf-net/Meta/TypeModel.cs:600)
        ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream source, System.Object value, System.Type type) (at Assets/Plugins/protobuf-net/Meta/TypeModel.cs:577)
        ProtoBuf.Serializer.Deserialize[PERSON_INFO] (System.IO.Stream source) (at Assets/Plugins/protobuf-net/Serializer.cs:77)
        Assets.Scripts.ResData.ResDataManager.ReadDataConfig[PERSON_INFO] (System.String FileName) (at Assets/Scripts/ResData/ResDataManager.cs:31)
        )


        期待您的回复,不甚感激。
        JumboWu:@DonaldW 能否,发一份您的工具我参考下,我的那里出问题了.因为我用的版本就是按照您的说明来着的。
        DonaldW:@Jump_Wu 一般这种情况是 代码-数据 的版本不一致
      • JumboWu:根据文章步骤,成功的导出。但,有个疑问:我在读取Python脚本导出*.data文件的时候,出错了。Protobuf-net自己序列化一个文件,同时读取该文件是没有问题的。

        Protobuf-net 作者对这个问题的描述,我试过了,都是不行,是不是我们导出的*.data文件格式Protobuf-net不支持??
      • 06150f7143bd:按 GetDataConfigPath 返回的路径,在 android 上读不到 .data 的数据,windows倒是可以

      本文标题:将xls转成protobuf供Unity使用的流程

      本文链接:https://www.haomeiwen.com/subject/gwcjtttx.html