赞
踩
ProtoBuf 是结构数据序列化方法,可简单类比于 XML、JSON,其具有以下特点:
我这边选择的版本为 ProtoBuf 3.5.x
一共需要两个步骤
从GitHub上获取完整版 传送门, 选择3.5.x的版本
这里有2条方式可供选择
(1)在unity中使用源码
Google.Protobuf这个文件夹直接放入到unity中
(2)在unity中使用Google.Protobuf.dll
使用vs打开它,用release去编译Google.Protobuf这个工程,在release这个目录下你会得到这个dll,放入到你的Libraries中
从GitHub上获取windows版本 传送门, 选择3.5.1的版本
在bin中找到我们要的protoc.exe
写好 proto 文件之后用 protoc 编译器将 .proto文件编译成目标语言。
测试文件内容
- // 指定版本
- syntax = "proto3";
- // C#中的namespace
- package ProtoTest
-
- option optimize_for = SPEED;
-
- // java文件路径
- option java_package = "com.montior.proto";
-
- // java文件名称
- option java_outer_classname = "MonitorData";
-
- // 消息结果。
- message MsgResult {
- // 结果码。
- int32 code = 1;
- // 错误消息。
- string err_msg = 2;
-
- }
-
- // 接收包
- message TaskProtocol {
- // 数据类型
- int32 packType = 1;
-
- // 具体数据
- bytes content = 3;
-
- }
-
- // 包的类型
- enum PackType {
- LOGIN = 0;
- CREATE_TASK = 2;
- DELETE_TASK = 3;
- }
-
- message LoginPack{
- string username = 1;
- }
-
- message LoginPack2{
- string username = 1;
- }
-
- message CreateTaskPack{
- string taskId = 1;
- string taskName = 2;
- }
message:消息类型,类似于一个类
package:包名,CSharp中的命名空间,用来防止不同消息类型的冲突
enum:枚举,这个需要我说吗?
option:选项,说明下我这边用到的
option java_package = “com.example.foo”;// java文件路径
option java_outer_classname = “Ponycopter”;// java文件名称
option optimize_for = SPEED;//可以被设置为 SPEED, CODE_SIZE,or LITE_RUNTIME。这些值将通过如下的方式影响C++及java代码的生成:
注:以上选项,CSharp都用不着的,就是写着玩儿....
protobuf 数据类型 | 描述 | C++ | |
bool | 布尔类型 | bool | |
double | 64位浮点数 | double | |
float | 32为浮点数 | float | |
int32 | 32位整数、 | int | |
uin32 | 无符号32位整数 | unsigned int | |
int64 | 64位整数 | __int64 | |
uint64 | 64为无符号整 | unsigned __int64 | |
sint32 | 32位整数,处理负数效率更高 | int32 | |
sing64 | 64位整数 处理负数效率更高 | __int64 | |
fixed32 | 32位无符号整数 | unsigned int32 | |
fixed64 | 64位无符号整数 | unsigned __int64 | |
sfixed32 | 32位整数、能以更高的效率处理负数 | unsigned int32 | |
sfixed64 | 64为整数 | unsigned __int64 | |
string | 只能处理 ASCII字符 | std::string | |
bytes | 用于处理多字节的语言字符、如中文 | std::string |
指定字段 | 说明 |
required | 表示是一个必须字段,必须相对于发送方,在发送消息之前必须设置该字段的值,对于接收方,必须能够识别该字段的意思。发送之前没有设置required字段或者无法识别required字段都会引发编解码异常,导致消息被丢弃。 |
optional | 表示是一个可选字段,可选对于发送方,在发送消息时,可以有选择性的设置或者不设置该字段的值。对于接收方,如果能够识别可选字段就进行相应的处理,如果无法识别,则忽略该字段,消息中的其它字段正常处理。---因为optional字段的特性,很多接口在升级版本中都把后来添加的字段都统一的设置为optional字段,这样老的版本无需升级程序也可以正常的与新的软件进行通信,只不过新的字段无法识别而已,因为并不是每个节点都需要新的功能,因此可以做到按需升级和平滑过渡。 |
repeated | 表示该字段可以包含0~N个元素。其特性和optional一样,但是每一次可以包含多个值。可以看作是在传递一个数组的值。 |
UnityProject
-Asset
--Libraries
---Google.Protobuf // Protobuf源文件/dll文件
--Scripts/Editor/Proto2CSEditor // 放置.proto文件转化为cs的代码
--Scripts/ProtoMessage // 放置转化的cs的代码
-Proto
--monitorData.proto //放置.proto文件
--protoc.exe //
- [MenuItem("Tools/Proto2CS")]
- public static void AllProto2CS()
- {
- string rootDir = Environment.CurrentDirectory;
- string protoDir = Path.Combine(rootDir, "Proto/");
-
- string protoc;
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- protoc = Path.Combine(protoDir, "protoc.exe");
- }
- else
- {
- protoc = Path.Combine(protoDir, "protoc");
- }
-
- string hotfixMessageCodePath = Path.Combine(rootDir, "Assets", "Scripts", "ProtoMessage/");
-
- string argument2 = $"--csharp_out=\"{hotfixMessageCodePath}\" --proto_path=\"{protoDir}\" monitorData.proto";
-
- Run(protoc, argument2, waitExit: true);
-
- UnityEngine.Debug.Log("proto2cs succeed!");
-
- AssetDatabase.Refresh();
- }
-
- public static Process Run(string exe, string arguments, string workingDirectory = ".", bool waitExit = false)
- {
- try
- {
- bool redirectStandardOutput = true;
- bool redirectStandardError = true;
- bool useShellExecute = false;
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- redirectStandardOutput = false;
- redirectStandardError = false;
- useShellExecute = true;
- }
-
- if (waitExit)
- {
- redirectStandardOutput = true;
- redirectStandardError = true;
- useShellExecute = false;
- }
-
- ProcessStartInfo info = new ProcessStartInfo
- {
- FileName = exe,
- Arguments = arguments,
- CreateNoWindow = true,
- UseShellExecute = useShellExecute,
- WorkingDirectory = workingDirectory,
- RedirectStandardOutput = redirectStandardOutput,
- RedirectStandardError = redirectStandardError,
- };
-
- Process process = Process.Start(info);
-
- if (waitExit)
- {
- process.WaitForExit();
- if (process.ExitCode != 0)
- {
- throw new Exception($"{process.StandardOutput.ReadToEnd()} {process.StandardError.ReadToEnd()}");
- }
- }
-
- return process;
- }
- catch (Exception e)
- {
- throw new Exception($"dir: {Path.GetFullPath(workingDirectory)}, command: {exe} {arguments}", e);
- }
- }
- MsgResult result = new MsgResult
- {
- Code = -999,
- ErrMsg = "Error"
- };
-
- TaskProtocol msgResult = new TaskProtocol
- {
- PackType = 111,
- Content = result.ToByteString()
- };
-
- byte[] s = packer.SerializeTo(msgResult);
- Debug.Log("---------------------------------------------------");
-
-
- TaskProtocol response = new TaskProtocol();
- packer.DeserializeFrom(response, s);
-
- MsgResult responseMsgResult = new MsgResult();
- packer.DeserializeFrom(responseMsgResult, response.Content.ToByteArray());
-
- Debug.Log(response.PackType);
- Debug.Log(responseMsgResult.Code);
- Debug.Log(responseMsgResult.ErrMsg);
<!--暂无-->
如果这样你都还配置不好ProtoBuf,不知道怎么序列化和反序列化的话!!!!
那就多看几遍,哈哈哈
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。