欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Unity3D】在Unity中使用Protobuf(proto3)

程序员文章站 2022-05-13 20:24:16
...

有研究表明,一条消息数据,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一,ProtoBuf的优势还是很明显的。这里简单介绍哈使用

 

一、下载protobuf

https://github.com/google/protobuf/releases

选择protoc-3.6.0-win32.zip下载

 

二、编写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的类型,和其他语言类型的对比如下:

【Unity3D】在Unity中使用Protobuf(proto3)

(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)默认值

  1. string类型的默认值是空字符串
  2. bytes类型的默认值是空字节
  3. bool类型的默认值是false
  4. 数字类型的默认值是0
  5. enum类型的默认值是第一个定义的枚举值
  6. message类型(对象,如上文的SearchRequest就是message类型)的默认值与语言相关
  7. 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

 

【Unity3D】在Unity中使用Protobuf(proto3)

(2)打开cmd 执行

protoc --version

显示libprotoc  3.6.0即配置完毕

【Unity3D】在Unity中使用Protobuf(proto3)

 

四、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
 

【Unity3D】在Unity中使用Protobuf(proto3)

若配置了环境变量:

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

【Unity3D】在Unity中使用Protobuf(proto3)

 

五、然后就看到目标路径生成了Msg.cs

(未完待续)

 

 

相关标签: protobuf