UN5L6——Protobuf协议生成

本章代码关键字

1
2
3
4
Process                        //进程类,可以运行某个可执行程序,如同在cmd或者powershell运行一个程序那样
process.StartInfo.FileName //可执行程序所在路径及其文件名
process.StartInfo.Arguments //可执行程序执行时要输入的参数
process.Start() //运行可执行程序

利用protoc.exe编译器生成脚本文件

  1. 打开cmd或powershell窗口(如果你使用VSCode,你可以直接使用它的终端)
  2. 进入protoc.exe所在文件夹(输入cd protoc.exe所在路径​,或者可以直接将exe文件拖入cmd窗口中)
  3. 输入转换指令:protoc.exe -I=配置路径 --csharp_out=输出路径 配置文件名

注意:路径不要有中文和特殊符号,避免生成失败

Protobuf 通过配置生成脚本文件,主要使用的就是 protoc.exe可执行文件,我们需要记住对应的生成指令

测试生成对象是否能使用

  • 调用Protobuf生成的类,需要使用在proto文件内指定的命名空间,类的各种变量的调用本身无差异
  • 由Protobuf生成的List​变量和Dictionary​变量本质上不是C#自带的List​和Dictionary​,但可以当作C#自带的List​和Dictionary​使用
  • 在另一个生成的脚本中的类,如果命名空间不同,需要命名空间点出来使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using GamePlayerTest;
using UnityEngine;

public class Lesson40 : MonoBehaviour
{
void Start()
{
TestMsg msg = new TestMsg();
msg.TestBool = true;
//对应的和List以及Dictionary的使用方式是一样的,数组和字典对象
msg.ListInt.Add(1);
print(msg.ListInt[0]);
msg.TestMap.Add(1, "唐老狮");
print(msg.TestMap[1]);
//枚举
msg.TestEnum = TestEnum.Boss;
//内部枚举
msg.TestEnum2 = TestMsg.Types.TestEnum2.Boss;
//其他类对象
msg.TestMsg2 = new TestMsg2();
msg.TestMsg3.TestInt32 = 99;
//其他内部类对象
msg.TestMsg3 = new TestMsg.Types.TestMsg3();
msg.TestMsg3.TestInt32 = 55;
//在另一个生成的脚本中的类,如果命名空间不同,需要命名空间点出来使用
msg.TestHeart = new GameSystemTest.HeartMsg();
}
}

实现快捷生成所有消息协议的工具

我们可以通过DirectoryInfo​和Directory​来获取所有的proto文件名,通过Process​来执行可执行程序,来循环生成所有的代码文件
通过以上的类,我们可以方便的快速生成代码,甚至可以快速生成不同语言的代码

Process​是进程类,它可以让我们运行一个可执行程序,如同在cmd或者powershell运行一个程序那样,会使用以下方法:

  • process.StartInfo.FileName​:可执行程序所在路径及其文件名
  • process.StartInfo.Arguments​:可执行程序执行时要输入的参数
  • process.Start()​:运行可执行程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
using System.Diagnostics;
using System.IO;
using UnityEditor;

public class ProtobufTool
{
//Protobuf编译器路径
private static string PROTOC_PATH = System.Environment.CurrentDirectory + "\\Protobuf\\protoc.exe";
//proto文件路径
private static string PROTO_PATH = System.Environment.CurrentDirectory + "\\Protobuf\\proto";
//C#文件存储的路径
private static string CSHARP_PATH = System.Environment.CurrentDirectory + "\\Protobuf\\csharp";
//C++文件存储的路径
private static string CPP_PATH = System.Environment.CurrentDirectory + "\\Protobuf\\cpp";
//Java文件存储的路径
private static string JAVA_PATH = System.Environment.CurrentDirectory + "\\Protobuf\\java";

[MenuItem("ProtobufTool/生成C#代码")]
private static void GenerateCSharp()
{
GenerateCodeFiles("csharp_out", CSHARP_PATH);
}

[MenuItem("ProtobufTool/生成C++代码")]
private static void GenerateCpp()
{
GenerateCodeFiles("cpp_out", CPP_PATH);
}

[MenuItem("ProtobufTool/生成Java代码")]
private static void GenerateJava()
{
GenerateCodeFiles("java_out", JAVA_PATH);
}

//生成对应脚本的方法
private static void GenerateCodeFiles(string outCodeType, string outPath)
{
//第一步:遍历对应协议配置文件夹,得到所有的配置文件
DirectoryInfo directory = Directory.CreateDirectory(PROTO_PATH);
//获取对应文件夹下所有文件消息
FileInfo[] files = directory.GetFiles();
for (int i = 0; i < files.Length; i++)
{
//只有是配置文件夹才能用于生成
if (files[i].Extension == ".proto")
{
//第二步:根据文件内容,来生成对应的C#脚本(需要使用C#当中的Process类)
Process cmd = new Process();
cmd.StartInfo.FileName = PROTOC_PATH;
//命令
cmd.StartInfo.Arguments = $"-I={PROTO_PATH} --{outCodeType}={outPath} {files[i]}";
//执行
cmd.Start();
UnityEngine.Debug.Log(files[i] + "生成结束");
}
}
UnityEngine.Debug.Log("所有内容生成结束");
}
}