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

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容