写在前面

  • 起因:我看到工作项目使用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. Java8函数式编程(A)

    将行为作为数据传递 函数编程的最直接的表现,莫过于将函数作为数据自由传递,结合泛型推导能力,使代码表达能力获得飞一般的提升. Java8怎么支持函数式编程? 主要有三个核心概念: 函数接口(Funct ...

  2. HFS~HTTP File Server 2.4rc2 20191231

    后台,打卡,这有的 电脑 PC   浏览器 打开 安卓平台,浏览器,打开,界面

  3. SparkRDD所有算子操作,建议全部手敲一遍

    说明: 1.以下方法全部来自这个RDD.scala,可以自己看源码 2.使用$SPARK_HOME/bin/spark-shell运行代码 3.注释部分是运行结果 //org.apache.spark ...

  4. Iframe 默认高度、宽度

    项目中还在使用 Iframe ,一次看代码时发现 Iframe 没有指定高度.宽度,可是在页面上显示的时候却有高度.宽度.想着应该是 Iframe 的默认值,于是写了一个简单的页面,代码如下: 1 & ...

  5. tiktok运营工具

    1.自信点!这就是TikTok最全运营工具合集! - 知乎 (zhihu.com) 2.骄傲的和大家说!这就是TikTok最全运营工具合集! - 知乎 (zhihu.com) 3.如何批量去水印下载抖 ...

  6. 安装gitlab的总结

    安装过程参考文档 http://www.linuxe.cn/post-520.html https://www.bilibili.com/read/cv4602641 备注要点: 1.gitlab安装 ...

  7. 每日一抄 Go语言聊天服务器

    server.go package main import ( "bufio" "fmt" "log" "net" ) ...

  8. SQL中使用JOIN时,过滤条件的位置

    sql语句 (SELECT * FROM t1 WHERE {subquery_where_condition}) a JOIN (SELECT * FROM t2 WHERE {subquery_w ...

  9. Jenkins+Appium+Pytest+Allure集成

    前提: 已经部署好了Jenkins环境,包括工具配置等 我的环境: Jenkins服务由安装在虚拟机上的Docker启动 Appium相关运行环境安装在虚拟机所在的主机上windows 方式:在Jen ...

  10. Feign熔断

    在Feign中使用 @EnableFeignClients中已经默认打开了断路器功能,所以这里的启动类上不需要再加@EnableCircuitBreaker注解 只需要在@FeignClient中为f ...