Unity C# 网络学习(十二)——Protobuf生成协议
一.安装
- 去Protobuf官网下载对应操作系统的protoc,用于将.proto文件生成对应语言的协议语言文件
- 由于我使用的是C#所以可以使用提供的C#的序列化反序列化的项目,然后自己编译出DLL放入Unity中使用
二.Protobuf 配置的规则(.proto文件的语法)
syntax = "proto3";
package GamePlayerTest;
import "test2.proto";
message TestMsg1 {
float testF = 1;
double testD = 2;
int32 testInt32 = 3;
int64 testInt64 = 4;
sint32 testSInt32 = 5;
sint64 testSInt64 = 6;
uint32 testUInt32 = 7;
uint64 testUInt64 = 8;
fixed32 testFixed32 = 9;
fixed64 testFixed64 = 10;
sfixed32 testSFixed32 = 11;
sfixed64 testSFixed64 = 12;
repeated int32 arr_int32 = 13;
repeated string arr_string = 14;
map<int32,string> map1 = 15;
TestEnum1 test_enum1 = 16;
message TestMsg2{
int32 test_int32 = 1;
}
TestMsg2 test_msg2 = 17;
enum TestEnum2{
NORMAL = 0;
BOSS = 1;
}
TestEnum2 test_enum2 = 18;
GameSystemTest.HeartMsg heart_msg = 19;
}
enum TestEnum1{
NORMAL = 0;
BOSS = 5;
}
syntax = "proto3";
package GameSystemTest;
message HeartMsg{
int64 time = 1;
}
三.生成对应的C#代码
- 打开cmd窗口
- 进入protoc.exe所在文件夹(也可以直接拖入到cmd中)
- 输入转换指令
- protoc.exe -I=配置路径 =csharp_out=输出路径 配置文件名
四.封装快捷生成协议文件
public static class GenerateProtobuf
{
private const string ProtocPathExe = @"D:\Unity_Project\AgainLearnNet\Protobuf\protoc.exe";
private const string ProtoPath = @"D:\Unity_Project\AgainLearnNet\Protobuf\proto";
private const string OutPath = @"D:\Unity_Project\AgainLearnNet\Protobuf\csharp";
[MenuItem("Protobuf/GenerateCSharp")]
private static void GenerateCSharp()
{
DirectoryInfo directoryInfo = new DirectoryInfo(ProtoPath);
FileInfo[] fileInfos = directoryInfo.GetFiles();
foreach (var fileInfo in fileInfos)
{
if(fileInfo.Extension != ".proto")
continue;
Process cmd = new Process();
cmd.StartInfo.FileName = ProtocPathExe;
cmd.StartInfo.Arguments = $"-I={ProtoPath} --csharp_out={OutPath} {fileInfo.Name}";
cmd.Start();
}
}
}
五.协议的序列化和反序列化
1.文本流
private void Start()
{
MyTestMsg myTestMsg = new MyTestMsg();
myTestMsg.PlayerId = 1;
myTestMsg.Name = "zzs";
myTestMsg.Friends.Add("wy");
myTestMsg.Friends.Add("pnb");
myTestMsg.Friends.Add("lzq");
myTestMsg.Map.Add(1,"ywj");
myTestMsg.Map.Add(2,"zzs");
string path = Application.persistentDataPath + "/testMsg.msg";
using (FileStream fs = new FileStream(path,FileMode.Create))
{
myTestMsg.WriteTo(fs);
}
MyTestMsg newMyTestMsg;
using (FileStream fs = new FileStream(path,FileMode.Open))
{
newMyTestMsg = MyTestMsg.Parser.ParseFrom(fs);
}
Debug.Log(newMyTestMsg.PlayerId);
Debug.Log(newMyTestMsg.Name);
Debug.Log(newMyTestMsg.Friends.Count);
Debug.Log(newMyTestMsg.Map[1]);
Debug.Log(newMyTestMsg.Map[2]);
}
2.内存流
private void Start()
{
MyTestMsg myTestMsg = new MyTestMsg
{
PlayerId = 1,
Name = "zzs"
};
myTestMsg.Friends.Add("wy");
myTestMsg.Friends.Add("pnb");
myTestMsg.Friends.Add("lzq");
myTestMsg.Map.Add(1,"ywj");
myTestMsg.Map.Add(2,"zzs");
byte[] buffer;
using (MemoryStream ms = new MemoryStream())
{
myTestMsg.WriteTo(ms);
buffer = ms.ToArray();
}
MyTestMsg newMyTestMsg;
using (MemoryStream ms = new MemoryStream(buffer))
{
newMyTestMsg = MyTestMsg.Parser.ParseFrom(ms);
}
Debug.Log(newMyTestMsg.PlayerId);
Debug.Log(newMyTestMsg.Name);
Debug.Log(newMyTestMsg.Friends.Count);
Debug.Log(newMyTestMsg.Map[1]);
Debug.Log(newMyTestMsg.Map[2]);
}
六.Protobuf的序列化和反序列化(优化调用方式)
private void Start()
{
MyTestMsg myTestMsg = new MyTestMsg
{
PlayerId = 1,
Name = "zzs"
};
myTestMsg.Friends.Add("wy");
myTestMsg.Friends.Add("pnb");
myTestMsg.Friends.Add("lzq");
myTestMsg.Map.Add(1,"ywj");
myTestMsg.Map.Add(2,"zzs");
byte[] buffer = myTestMsg.ToByteArray();
MyTestMsg newMyTestMsg = MyTestMsg.Parser.ParseFrom(buffer);
Debug.Log(newMyTestMsg.PlayerId);
Debug.Log(newMyTestMsg.Name);
Debug.Log(newMyTestMsg.Friends.Count);
Debug.Log(newMyTestMsg.Map[1]);
Debug.Log(newMyTestMsg.Map[2]);
}
|