Unity程序员Unity

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

2014-06-25  本文已影响7710人  DonaldW

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项目使用步骤

目录解释
环境准备步骤

环境准备步骤到此结束。

使用方法

通用项目准备步骤

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

  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
上一篇下一篇

猜你喜欢

热点阅读