写在前面

  • 起因:我看到工作项目使用protobuf来做序列化时脑子冒出许多问号,“以前我按《Unity3D网络游戏实战》做坦克游戏时为了让客户端和服务器使用统一协议用到了protobuf,怎么没有啥序列化的印象?”,“为什么非得选protobuf而不是其他工具?”,“序列化时常看到的MemoryStream和FileStream,以及StreamWriter、StreamReader这些到底是什么关系?”等等等等,于是我决定在自己的测试项目上从头开始摸索protobuf,以能成功用上protobuf为最终目标,顺便解决我这一系列问题。
  • 本篇博文主要记录我用头开始使用protobuf遇到的种种状况和问题解答,重点在踩坑而非如何使用protobuf。如何使用protobuf部分这里可以概括为:其实项目使用的是protobuf-net而非protobuf,从该谷歌网页下载protobuf-net r668压缩包,解压文件后使用里面的protobuf-net.dll和protogen.exe。
  • 本篇博文按“我的问题是什么”——>“解决问题过程记录”来组织。
  • Unity版本:2017.4.39f1

踩坑

  • protobuf是什么?——> 我先去翻了翻官网,官网首页说它是一个“无关语言无关平台且可扩展的序列化工具”,但这简单一句话并不能让我体会它的好,于是我去翻了翻博客们但也没找到更具体一点的解释,最后我还是回到了官网找到了具体解释(在官网Guides - Tutorials - Why use protocol buffers?),简单来说:它以我们会想到的几种序列化实现方法举例说明有哪些麻烦,而protobuf搞定了这些麻烦。
  • 为什么非得选protobuf而不是其他工具?——> 在主程的博客上,我看到了他选protobuf的原因,简单来说:他考虑过Unity自带的scriptObject和挂脚本,但该方法不支持热更;考虑过Xml,但它不支持Unity一些属性(如Color)序列化,而且影响重构(例如重构时改变量名是很常见的一件事),所以最后选用protobuf。
  • 怎么用protobuf序列化?——> (这里开始我在个人测试项目上操作,遇到状况颇多)
    • 我看了官网Tutorials,再看了它Github首页上的readme,它要安两个东西,一个是编译器protoc(其实最后要用的是protoc.exe),它负责把.proto文件生成对应.cs文件;另一个是dll,它负责代码实际功能(编码解码、序列化等)。但项目里用的不是谷歌官方的,而是第三方工具protobuf-net(当然它也是基于protobuf做的)。
    • 翻到的博客很多都没写到我关注的重点,有的把protobuf-net和protobuf混为一谈,有的不介绍为什么用protobuf-net而不是protobuf,而且protobuf安装说明总得有参考官方英文说明吧,也没列出参考,就直接讲如何安装了。
    • 我的项目Unity版本是2017.4.39f1,它用的是.net 3.5(如下图),但protobuf不支持.net 3.5(这在它Github上源码的readme文档里解释得很清楚,不过最开始我还是狂搜别人博客才知道大家不用官方protobuf的原因是这样),所以大家才选择了使用protobuf-net。

    • protobuf-net的Github上的What Files Do I Need文档里说,我会用到的是它的dll和protogen工具,因为我想直接拿到dll,所以直接在源码文件夹里搜protobuf-net.dll,发现有很多protobuf-net.dll都放在assorted文件夹下,而看这个文件夹的readme上作者说这个文件夹什么杂项啥都有。到底用哪个dll呢?作者的文件夹结构把我绕晕了……
    • 参考这篇博文,我打算编protobuf-net源码来得到它的dll,但工程用VS2015打开会有XML报错,放弃这个安装方向,转而参考这篇博文用NuGet来安装,发现protobuf-net最新版(此时最新版为3.0.62,它需要.net4.6.1).net版本比Unity要求高,而这里能支持.net3.5的protobuf-net最高版本就是2.4.6。

      NuGet帮我下在这了,但我并不知道哪些文件夹内容需要放Unity,这里也并没有protogen工具……

      于是我想去Github下源码看看能不能解决问题,我回到protobuf-net的Github上,用view all tag跳到release面板,查到能下的竟是2.4.5版本(它也没有日志说明支持.net版本)

点击release查看所有版本

      把2.4.5版本源码下载后,再打开工程仍有xml报错,查了解决方法要么在VS2015里一个个改错要么用VS2017,我决定去用VS2017。用VS2017后打开工程发现又有.net版本问题,我试图下了对应.net的SDK来解决但搞不定!于是回到前面NuGet下载protobuf-net2.4.6那步,这里的protobuf-net.dll我用的是net35文件夹里的dll,在Unity的Plugins文件夹下新建一个名为protobuf-net文件夹,将dll放入。我也试过放高于.net35版本的dll,显然在Unity里点dll时会看到报错。

      虽然NuGet可以帮下protobuf-net.dll,但protogen工具到底从哪里找呢?我试过用DotNetTool命令行工具下了从高到低好几个版本的protogen,但即使是NuGet上最低版本1.0.6的protogen它生成的.cs脚本放Unity里仍会有语法报错(用了C#6内容,当前Unity是C#4.0),而语法报错解决方法是Unity要升到.net4.6才行……

      我试过用G站上的protobuf-net2.4.5里的protogen工程生成protogen工具,也仍有语法报错。最后参考这个博文,我还是回到谷歌网页下了protobuf-net r668版本,直接用里面的protogen.exe(这里我也试过用G站上的protobuf-net r668源码生成protogen.exe,这次生成竟然成功了!)

      虽然之前我用NuGet下的protobuf-net2.4.6版本的protobuf-net.dll放Unity里没问题,但为了配合protobuf-netr668版本,最后还是用protobuf-netr668文件夹里的protobuf-net.dll。

    • 总的来说,我从谷歌网页下载protobuf-net r668,使用了里面的protobuf-net.dll和protogen.exe。

      • 在protogen.exe文件夹下随便建个.bat文件,内容如下图这么写,然后运行该bat,就能看到protogen使用帮助。

protogen帮助说明

        下图是执行protogen正确写法示例:

  • protobuf-net安好了,怎么用它的序列化呢?——> 说明就在protobuf-net的Github首页上,特性很少,使用极其简单。
  • 序列化时常看到的MemoryStream和FileStream,以及StreamWriter、StreamReader这些到底是什么关系?——>
    • 对于Stream,《深入理解C#》和《C#图解教程》、《CLR via C#》都没有讲,连基本IO读写都没讲。
    • 资料来自《精通C#》,以下内容是我的概括:
      • File和FileInfo关系:两者用哪个都行,不过用File能省更多代码,而用FileInfo会能得到更多文件信息。同理Directory和DirectoryInfo。
      • FileStream只能处理byte(读byte写byte),当然文档里仍然是正常显示(内容是什么显示就是什么)。
      • StreamWriter、StreamReader基于字符操作,就是用来WriteLine(…)这些,StringWriter意思差不多,只是和StreamWriter内部细节不太一样。
      • BinaryWriter基于二进制操作,文档里是二进制(就是看上去是乱码)。
      • 最后书上没讲MemoryStream内存流,只提了一句要保存为文件就用FileStream,放内存就用MemoryStream……我在msdn上查了MemoryStream,它说序列化用它性能更好,我在谷歌上没搜到“使用MemoryStream性能更好”的好举例。

  • 以前我按《Unity3D网络游戏实战》做坦克游戏时为了让客户端和服务器使用统一协议用到了protobuf,怎么没有啥序列化的印象?——>我回头去看书和做的工程了,它实际上用的就是protobuf-net工具,协议就是编码(序列化)后才收发的。书作者简单介绍了两句protobuf和protobuf-net的关系,直接给了protobuf-net的dll和protogen。

【Unity】protobuf故意踩坑记的更多相关文章

  1. Unity接入AbMob踩坑记

    之前是配置好的环境,不知道怎么突然就不正常了. 一直弹出下面的报错: Error running CocoaPods. Please ensure you have at least version ...

  2. Unity打包IOS踩坑记

    1. Xcode不显示模拟器 之前一直用真机调试,就没注意模拟器.今天要上传版本要用到模拟器截图,发现竟然Xcode的运行选项竟然没有显示模拟器. 也是网上找了各种方法,修改各种设置,清了各种文件夹都 ...

  3. Hook踩坑记:React Hook react-unity-webgl

    自公司前后分离上手React以来,一个坑一个坑的踩,Class的全生命周期云里雾里,还么屡明白,就抱上了Hook的大腿不松手,确实爽到飞起.修改到Hook的过程基本比较顺畅,直接少了三分之一的代码,组 ...

  4. Spark踩坑记——Spark Streaming+Kafka

    [TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...

  5. Spark踩坑记——数据库(Hbase+Mysql)

    [TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...

  6. 【踩坑记】从HybridApp到ReactNative

    前言 随着移动互联网的兴起,Webapp开始大行其道.大概在15年下半年的时候我接触到了HybridApp.因为当时还没毕业嘛,所以并不清楚自己未来的方向,所以就投入了HybridApp的怀抱. Hy ...

  7. Spark踩坑记——共享变量

    [TOC] 前言 Spark踩坑记--初试 Spark踩坑记--数据库(Hbase+Mysql) Spark踩坑记--Spark Streaming+kafka应用及调优 在前面总结的几篇spark踩 ...

  8. Spark踩坑记——从RDD看集群调度

    [TOC] 前言 在Spark的使用中,性能的调优配置过程中,查阅了很多资料,之前自己总结过两篇小博文Spark踩坑记--初试和Spark踩坑记--数据库(Hbase+Mysql),第一篇概况的归纳了 ...

  9. djangorestframework+vue-cli+axios,为axios添加token作为headers踩坑记

    情况是这样的,项目用的restful规范,后端用的django+djangorestframework,前端用的vue-cli框架+webpack,前端与后端交互用的axios,然后再用户登录之后,a ...

  10. HttpWebRequest 改为 HttpClient 踩坑记-请求头设置

    HttpWebRequest 改为 HttpClient 踩坑记-请求头设置 Intro 这两天改了一个项目,原来的项目是.net framework 项目,里面处理 HTTP 请求使用的是 WebR ...

随机推荐

  1. 微信小程序循环数组展示数据点击当前改变当前按钮状态

    Html: <view class="container" wx:for="{{arr}}" wx:key="*"> //这里循 ...

  2. (K8s学习笔记八)Pod的扩缩容

    1.手动扩容机制 示例:对busybox-deployment手动扩缩容 apiVersion:apps/v1 kind: Deployment metadata: name: busybox-dep ...

  3. TODO留学小程序,展开,收起失效

    text设置user-select=true后,display: -webkit-box 失效? https://developers.weixin.qq.com/community/develop/ ...

  4. servlet和spring框架的关系

    1.Servlet是什么? servlet就是一个Java接口,是JavaEE规范的一种,主要是为了扩展Java作为Web服务的功能. 由其他内部厂商如tomcat,JBoss内部实现web的功能. ...

  5. C# 开源NuGet插件

    ExcelDataReader  开源免费,Excel读取插件 GitHub - ExcelDataReader/ExcelDataReader: Lightweight and fast libra ...

  6. css 多行隐藏

    overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box- ...

  7. [AGC013B] Hamiltonish Path

    个人思路: 随便从一个节点开始搜索,只要当前节点不满足条件,随便找一个与它有边相连,不在序列里的节点加入序列.因为要么中途停止,要么把所有节点遍历一遍,一定能找到一个端点. 我们直接从节点 \(1\) ...

  8. 打卡node day06 ---登录和注册接口

    1, nodemon 自动更新代码 npm i -g nodemon 启动: nodemon server.js 2,注册接口 1)目录结构 2)server.js const express = r ...

  9. 封装ajax、获取上一页面传参的方法

    1.封装ajax var defaultUrl = 'http://192.168.1.1:3000/' function post_data(url,data,successfn,errorfn){ ...

  10. tomcat 2 - 默认连接器精简版

    tomcat 将一个包中所有类使用的错误信息存储在 properties 文件中,每个包有一个  properties 文件.每个 properties 文件都是用 org.apache.catali ...