目录
1.介绍
1.1 什么是Protobuf
1.2 Protobuf和其他数据序列化方案对比
2.下载Protobuf
2.1 方案一 使用VS的Nuget包管理器进行安装(推荐)
2.1.1安装Protobuff包
2.1.2拷贝.dll文件
2.2 方案二 从Github下载并自己生成.dll
2.2.1 下载Probuff
2.2.2 VS打开解决方案
2.2.3 安装.NET SDK
2.2.4 生成.dll文件
3.使用Protoc工具生成.cs文件
3.1 下载Protoc
3.2 进入Bin文件夹目录
3.3 写一个.proto例子
3.4 使用proto.exe将.proto转换成可以在C#中使用的.cs文件
4.在Unity中使用Protobuff
4.1 将生成的.cs文件导入我们的Unity项目中
4.2 建一个Proto工具类,用来进行对我们的数据进行序列化和反序列化
4.3 写一个测试类
简单小结
1.介绍
1.1 什么是Protobuf
Protobuf,全程“Protocol Buffers”,是Google公司开发的一种对数据进行序列化/反序列化的技术。目前比较广泛地被用在网络传输通信中,作为一种数据交换格式进行使用
1.2 Protobuf和其他数据序列化方案对比
序列化文件大小 | 可读性 | 跨语言 | 跨平台 | 性能 | 易用性 | 适用场景 | |
XML | 大 | 高,包含所有层级结构和信息 | 支持 | 支持 | 低 | 复杂,像Excel一样逐节点查询 | 配置文件、定义协议等 |
Json | 较小 | 较高,所有数据以键值对形式储存 | 支持 | 支持 | 较高 | 简单 | 轻量级的数据存储和网络传输通信 |
Protobuf | 小 | 低,不包含字段名等信息,且需要适用专门的工具进行反序列化 | 支持 | 支持 | 高 | 较复杂,需要自己定义Proto数据结构,但序列化反序列化过程简单 | 高性能,低带宽的网络传输通信 |
二进制 | 极小 | 低,全是0和1二进制字节 | 不支持 | 不支持 | 极高 | 简单 | 有加密需求的大规模网络传输通信,数据存储等 |
2.下载Protobuf
选择一个版本,笔者这边以V3.23.3版本举例
2.1 方案一 使用VS的Nuget包管理器进行安装(推荐)
2.1.1安装Protobuff包
点击VS顶部工具栏→工具→NuGet包管理器→管理解决方案的NuGet程序包
点击浏览,搜索proto,点击Google.Protobuff,选中Assembly-Csharp程序集,选择跟我们合适的版本号进行安装
2.1.2拷贝.dll文件
安装成功后会在我们项目的Package文件夹下生成这几个文件夹,我们进入选中的这几个文件夹,选择lib→.netstandard2.0→各自的.dll文件,不然在代码中无法识别API
比如System.Memory中就是这个
在Unity项目Plugins目录导入上面这四个.dll文件,就可以正常使用了,生成这个.dll文件只需一次就行了,后续只要Unity或.NET版本相同,都可以重复进行使用
2.2 方案二 从Github下载并自己生成.dll
2.2.1 下载Probuff
和Protoc-xx版本-你的系统版本.zip
上面的Github链接Github链接Github链接,选择你要使用的版本,点进去,往下拉找到Protobuf-xx版本.zip,下载下来
解压出来是这样,选择你的语言版本打开,我们Unity是用的.NET,也就是csharp版本
进去后找到src文件夹,点开
2.2.2 VS打开解决方案
使用VS打开这个Google.Protobuf.sln文件
如果项目成功打开,请跳转到2.2.4步骤继续下一步
2.2.3 安装.NET SDK
如果弹出这个窗口就代表你的电脑没有安装匹配的.NET SDK版本,请继续往下看
需要根据你的Unity版本下载安装匹配的.NET版本,那怎么看你的Unity适用的版本呢,可以在Unity顶部工具栏→Help→Unity Manual中查询
如果你安装unity的时候没有勾选安装Unity Document,也可以在官网找到
记得左上角切换成你的Unity版本
然后在搜索框搜索.net api,在搜索结果中找到.NET Profile support,点击进入
下拉就可以看到你的Unity版本所匹配的.NET版本了,上面的是Unity所使用的.NET版本,左边竖排的是.NET的不同平台版本,可以看到适配度最好的是.NET Standard版本
知道版本后,就可以去微软下载.NET了
进去后往下拉找到.NET Standard,他让我们直接下载.NET/.NET Core,我们可以点进右边看看具体对应的版本
选择一个合适的.NET/.NET版本,回到刚才的界面下载,笔者这边选择的是.Net 7.0版本,下载后直接安装就行了,这里需要注意的是,如果你的VS版本太低,是无法使用.NET 7.0的,可以使用VS Installer安装一下VS 2022版本
回到刚才的Protobuf文件夹下的src目录下,新建一个global.json脚本
里面填上你的.NET SDK版本号,这时候打开Google.Protobuf.sln就不会报错了
{
"sdk": {
"version": "7.0.407",
}
}
2.2.4 生成.dll文件
点击VS顶部工具栏的调试→开始运行(不调试),等待执行完毕
在src/Google.Protobuf就会生成一个bin目录,如果你刚才点的是调试,就会生成Debug目录,我们使用的是Release模式,生成了Release目录,里面就是这样
注意,这时候我们不要直接使用.netstandard2.0的版本,因为.netstandard2.0文件目录下没有生成System.Buffers.dll等文件,导入Unity无法正常识别
我们选择使用.net45的版本,点进去,将所有文件拷贝到你的Unity Assets目录下的Plugins文件夹下,建议建个Protobuf文件夹,放在里面,这时候就可以使用了
3.使用Protoc工具生成.cs文件
3.1 下载Protoc
在刚才的Github链接,下载protoc-xx版本-你的系统版本.zip,注意,protoc版本和之前下的protobuf版本得是完全一致的
解压完是这样
3.2 进入Bin文件夹目录
回到前面下的Protoc文件目录下,进入bin文件夹,可以看到里面只有一个protoc.exe文件
3.3 写一个.proto例子
在本目录下,新建一个.proto后缀的文件,这个就是我们定义的protobuf类型的数据结构,这里写一个Animal动物的例子
点开编辑你的数据结构
第一行指定使用的Proto版本的语法,不指定则默认使用Proto2处理,第二行定义了在C#中调用Animal的命名空间
这里例子中定义了三个字段,分别是字符串类型的动物类型,int整型的动物id号,float浮点型的动物重量,protobuff支持的其他数据类型可自行搜索
syntax="proto3";
package MyProtobufData; //自定义命名,在C#用使用这个数据结构需要using
message Animal
{
string Type = 1;
int32 ID = 2;
float Weight =3;
}
3.4 使用proto.exe将.proto转换成可以在C#中使用的.cs文件
建一个.bat批处理命令,这样就不用每次都非常麻烦地使用命令进行转换了
打开后编辑转换的命令,--proto_path就是.proto文件所在的路径,.(!!!注意,这里是个小点)代表protoc.exe所在的当前目录,空一格 ,后面再输入你的.proto文件路径和完整名字,--csharp_out是你指定的.cs文件生成的位置,笔者这边就不指定了,直接原目录生成
protoc.exe --proto_path =. Animal.proto --csharp_out=.
编辑完毕双击执行.bat文件,就会生成一个同名的.cs文件
4.在Unity中使用Protobuff
4.1 将生成的.cs文件导入我们的Unity项目中
4.2 建一个Proto工具类,用来进行对我们的数据进行序列化和反序列化
using Google.Protobuf;
using UnityEngine;
using System;
public class ProtobufMgr
{
public static byte[] Serialize(IMessage message)
{
return message.ToByteArray();
}
public static T DeSerialize<T>(byte[] packet) where T : IMessage, new()
{
IMessage message = new T();
try
{
return (T)message.Descriptor.Parser.ParseFrom(packet);
}
catch (Exception e)
{
throw e;
}
}
}
4.3 写一个测试类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyProtobufData;//记得using刚才.proto内定义的命名空间
using System;
using System.IO;
using System.Text;
public class ProtobufTest : MonoBehaviour
{
private void Start()
{
//定义一个四百斤的大胖橘
Animal animal = new Animal()
{
Type = "东北金渐层",
ID = 1,
Weight = 400,
};
//序列化
byte[] bytes = ProtobufMgr.Serialize(animal);
Debug.Log("长度"+bytes.Length);
Debug.Log(Encoding.UTF8.GetString(bytes));
Debug.Log("————————————————————————");
//反序列化
Animal newAnimal = ProtobufMgr.DeSerialize<Animal>(bytes);
Debug.Log(newAnimal.Type);
Debug.Log(newAnimal.ID);
Debug.Log(newAnimal.Weight);
}
}
可以看到成功进行了序列化和反序列化
简单小结
看完上面的步骤,你已经学会在Unity中使用Protobuf进行序列化了,我们进行网络传输通信时使用的就是byte[]字节数组序列,发送方发送数据结构序列化后的byte[],接收方收到byte[]反序列化成原来的数据结构,就成功进行了网络的通信