博主最近在使用谷歌框架的proto,想在unity下自动生成可用的.proto文件,进行轻量化传输。但不想自己去一个个的生成。所以,找了很多的办法,后来发现可以通过protoc.exe进行生成,但是只能单个命令行进行生成,无法批量编译出.proto文件。后来经过多方尝试,使用Unity框架可以很容易的批量生成proto文件。
一、下载.proto程序
从官网地址选择自己想要的版本,然后下下来放到Unity工程可访问的指定目录,例如:ProtoGen目录
二、将想要转换的proto所有文件打包放在一个文件夹下,注意有依赖 的一定要都放在文件夹下,避免转换时找不到定义的情况出现
三、调用编译函数,如果提示有错误自行解决,没有报错的话,就可以在对应的生成目录找到C#可用的对应的protobuff文件了。
具体代码如下:
public void GenProtoCSFile()
{
string protogen = Application.streamingAssetsPath + "/ProtoGen/protoc.exe";
string protoDir = Application.streamingAssetsPath + "/ProtoGen/Proto";
List<string> cmds = new List<string>();
if (!Directory.Exists(protoDir))
{
Debug.LogError("不存在Proto文件夹 path:"+ protoDir);
return;
}
DirectoryInfo folder = new DirectoryInfo(protoDir); // Proto所在路径
FileInfo[] files = folder.GetFiles("*.proto", SearchOption.AllDirectories);
Debug.LogError("protofile size:" + files.Length);
string outDir = Path.Combine(Application.streamingAssetsPath, "AssetBundles") + "/ProtoGen/OutDir";
if (!Directory.Exists(outDir)) // CSharp 输出路径
{
Directory.CreateDirectory(outDir);
}
foreach (FileInfo file in files)
{
string cmd = protogen + " --csharp_out=" + outDir + " -I " + protoDir + " " + file.FullName;
cmds.Add(cmd);
}
Cmd(cmds);
AssetDatabase.Refresh();
}
public void Cmd(List<string> cmds)
{
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.WorkingDirectory = ".";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardError = true;
process.OutputDataReceived += OutputHandler;
process.ErrorDataReceived += ErrorDataHandler;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
for (int i = 0; i < cmds.Count; i++)
{
process.StandardInput.WriteLine(cmds[i]);
}
process.StandardInput.WriteLine("exit");
process.WaitForExit();
}
private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
if (!string.IsNullOrEmpty(outLine.Data))
{
Debug.Log(outLine.Data);
}
}
private void ErrorDataHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
if (!string.IsNullOrEmpty(outLine.Data) && !outLine.Data.Contains("warning:"))
{
Debug.LogError(outLine.Data);
}
}