【Unity3D】在Unity中使用Protobuf(proto3)
有研究表明,一条消息数据,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一,ProtoBuf的优势还是很明显的。这里简单介绍哈使用
一、下载protobuf
https://github.com/google/protobuf/releases
二、编写proto原文件
syntax = "proto3";//标明proto版本
package protobuf;//包名
//一个message相当于一个类
//1,2,3不代表参数默认值,而是参数标签
//repeated 可以理解为数组
message StoreRequest {
string name = 1;
int32 num = 2;
int32 result = 3;
repeated string myList=4;
}
(1)版本号
对于一个pb文件而言,文件首个非空、非注释的行必须注明pb的版本,即syntax = "proto3";
,否则默认版本是proto2。
(2)Message
一个message类型看上去很像一个Java class,由多个字段组成。每一个字段都由类型、名称组成,位于等号右边的值不是字段默认值,而是数字标签,可以理解为字段身份的标识符,类似于数据库中的主键,不可重复,标识符用于在编译后的二进制消息格式中对字段进行识别,一旦你的pb消息投入使用,字段的标识就不应该再改变。数字标签的范围是[1, 536870911],其中19000~19999是保留数字。
(3)类型
每个字段的类型(int32
,string
)都是scalar的类型,和其他语言类型的对比如下:
(4)修饰符
如果一个字段被repeated
修饰,则表示它 是一个列表类型的字段,比如上面
repeated string myList=3;
等于是List<string> myList
如果你希望可以预留一些数字标签或者字段可以使用reserved修饰符:
message Login {
reserved 2, 15, 9 to 11;
reserved "lg", "bo";
string bo = 3; // 编译报错,因为‘bo’已经被标为保留字段
}
(5)默认值
- string类型的默认值是空字符串
- bytes类型的默认值是空字节
- bool类型的默认值是false
- 数字类型的默认值是0
- enum类型的默认值是第一个定义的枚举值
- message类型(对象,如上文的SearchRequest就是message类型)的默认值与语言相关
- repeated修饰的字段默认值是空列表。
注:如果一个字段的值等于默认值(如bool类型的字段设为false),那么它将不会被序列化,这样的设计是为了节省流量
(6)枚举
每个枚举值有对应的数值,数值不一定是连续的。第一个枚举值的数值必须是0且至少有一个枚举值,否则编译报错。编译后编译器会为你生成对应语言的枚举类。
message StoreRequest {
string name = 1;
int32 number = 2;
int32 result = 3;
enum CoinType
{
None=0;
CT_cny = 1;
CT_usd = 2;
CT_hkd = 3;
CT_jpy = 4;
CT_eur = 5;
}
CoinType coin = 4;
}
可以使用MessageType.EnumType
的形式引用定义在其它message类型中的枚举。
注:由于编码原因,出于效率考虑,官方不推荐使用负数作为枚举值的数值。
(7)Maps
pb中也可以使用map类型(官方并不认为是一种类型,此处称之为类型仅便于理解),绝大多数scalar类型都可以作为key,除了浮点型和bytes,枚举型也不能作为key,value可以是除了map以外的任意类型:
map<string, object> obj = 3;
map其实是一种语法糖,它等价于以下形式:
message MapField {
key_type key = 1;
value_type value = 2;
}
repeated MapField map_field = N;
注:map
类型字段不支持repeated
,value的顺序是不定的。
(8)包
你可以用指定package
以避免类型命名冲突:
package store.ba;
message Buy{...}
然后可以用类型的全限定名来引用它:
message Store{
...
store.ba.Buy buy=1;
..
}
指定包名后,会对生成的代码产生影响,生成的类会以你指定的package
作为包名。
这里不再做详细介绍,可以参照https://developers.google.com/protocol-buffers/docs/encoding?hl=zh-cn
三、配置环境变量
将解压出来的protoc.exe放在一全英文路径下,并把其路径名放在windows环境变量下的path下。
(1)以win7为例,右键我的电脑->属性->高级系统设置->环境变量->系统变量->双击修改 变量”path” ,添加protoc.exe的路径,即:
;E:\protoc-3.6.0-win32\bin
(2)打开cmd 执行
protoc --version
显示libprotoc 3.6.0即配置完毕
四、win+R打开cmd窗口执行以下命令
E:\protoc-3.6.0-win32\bin\protoc.exe -I=e:\protoc-3.6.0-win32\bin --csharp_out=e:\protoc-3.6.0-win32\bin e:\protoc-3.6.0-win32\bin\msg.proto
若配置了环境变量:
protoc -I=e:\protoc-3.6.0-win32\bin --csharp_out=e:\protoc-3.6.0-win32\bin e:\protoc-3.6.0-win32\bin\msg.proto
protoc -I=源地址 --csharp_out=目标地址 源地址/xxx.proto
五、然后就看到目标路径生成了Msg.cs
(未完待续)
推荐阅读
-
Unity3D在Preview中打印日志的方法
-
C#使用Protocol Buffer(ProtoBuf)进行Unity中的Socket通信
-
unity3d发布apk在android虚拟机中运行的详细步骤(unity3d导出android apk)
-
【Unity3D日常开发】在Unity中使用正则表达式
-
Protobuf在Cmake中的正确使用方法详解
-
TDD在Unity3D游戏项目开发中的实践
-
Unity3D在Preview中打印日志的方法
-
protobuf在unity中使用
-
C#使用Protocol Buffer(ProtoBuf)进行Unity中的Socket通信
-
unity3d发布apk在android虚拟机中运行的详细步骤(unity3d导出android apk)