Proto概念
Protocol buffers是一种可以将自定义的结构体序列化(反序列化)成字符流(byte[])的中间工具。对比Json、XML、二进制,在序列化速度上更快,占用内存上更小,但相对而言操作更麻烦。由于Proto工具提供的语言支持,支持用户可以在不同的语言中对同样数据结构进行序列化和反序列化。
Proto下载
获取地址:Releases · protocolbuffers/protobuf (github.com)
当前版本:v3.17.3
类库下载
由于我的前后端都是使用C#作为脚本语言,所以这里只下载C#的类库做演示。
工具下载
网页下拉就可以找到prptoc的下载链接。
我当前使用的是Windows 64位系统,所以下载win64版本。
使用方法
1.类库导入
解压下载好的类库压缩包,在目录下找到 Google.Protobuf.sln
文件。使用VS打开。
打开后,在解决方案资源管理器中选中Google.Protobuf
,右击,选择重新生成
。
等待VS生成完成后,接下选中Google.Protobuf
,右击,选择在资源管理器中打开文件夹
。然后在弹出的文件夹中上拉,找到最上方的bin
目录打开。接下来我们会看到Debug
或Release
目录,你们可能只有一个,是由于在VS编辑器中选择的编译模式不同而导致的。
随意打开其中一个。我们可以看到有如下四个不同版本的文件夹(因为使用Proto版本不同,生成的版本也有差异)。
**PS:**修改产生版本的方式
资源管理器中,双击
Google.Protobuf
,会打开Google.Protobuf.csproj
文件,找到<TargetFrameworks>
标签栏,在其中添加我们需要的版本(如图,我添加了net35版本),保存后重新生成项目即可。
在Unity中查看我们项目使用的.net版本,Edit-》ProjectSettings-》Player,一般来说我们尽量使用NET4.x版本,接下来我们也使用4.x版本作为演示。
打开我们前面生成的类库文件夹的net45版本,选中其中的四个dll文件,将其复制到我们Unity项目中。
这一过程可能会报错,这是由于你导入的dll重复了,删除其中一个dll即可。(但是在这里我没有解决,因为它的dll和unity包里的冲突了,如果我删除proto的dll,会导致序列化时无法找到该程序集,如果我删除Unity包里的,那我其他程序又会出错,这里解决了的朋友可以给我留言,让我借鉴下)
补充:可以使用老版本的protobuf,在3.10及之前的版本ProtoBuf编译后只会生成单个Dll,这样就避免了其他的dll重复。
2.自定义Proto文件
解压前面下载的Protoc工具压缩包,找到其目录下的bin
文件夹,然后在新建一个以.proto
为后缀的文件(如图)。
该文件可以使用记事本打开,我这里使用VS Code打开。在文件中输入如下内容,其中TestReuest就是我们定义的消息协议了(数据结构)。
syntax = "proto3";//标明proto版本
package protobuf;//包名
//一个message相当于一个类
//1,2,3不代表参数默认值,而是参数标签
//repeated 可以理解为List
message TestRequest {
string name = 1;
int32 num = 2;
int32 result = 3;
repeated string myList = 4;
}
然后我们在bin
文件下按住Shift键
,右击,选择在此处打开Powershell
。
在窗口中输入如下命令,即可看到在目录下生成了一个C#文件。【注意:Protoc工具只能访问同级、子级目录下的Proto文档,无法访问父级路径、绝对路径】
.\proto.exe TestProto.proto --csharp_out=./
将其复制到Unity中,并创建一个脚本GameStart
。
using Google.Protobuf;
using Protobuf;
using System.Text;
using UnityEngine;
public class GameStart : MonoBehaviour
{
void Start()
{
//创建对象
TestRequest sestRequest = new TestRequest()
{
Name = "测试",
Num = 2222,
Result = 3333,
};
sestRequest.MyList.Add("AAA");
sestRequest.MyList.Add("BBB");
sestRequest.MyList.Add("CCC");
//序列化成字节流
byte[] bytes = sestRequest.ToByteArray();
StringBuilder stringBuilder=new StringBuilder();
foreach (var item in bytes)
{
stringBuilder.Append(item);
}
Debug.Log(stringBuilder.ToString());
//使用Socket发送消息
//Socket.Send(bytes);
//反序列化成对象
TestRequest newTestRequest = TestRequest.Parser.ParseFrom(bytes);
Debug.Log(sestRequest.Name);
Debug.Log(sestRequest.Num);
Debug.Log(sestRequest.Result);
foreach (var item in newTestRequest.MyList)
{
Debug.Log(item);
}
}
}
3.运行游戏
创建场景,挂载GameStart
对象,运行游戏。