Unity | 集成 Protobuf(proto 转 cs 插件及序列化与反序列化)

2024-04-25 18:12

本文主要是介绍Unity | 集成 Protobuf(proto 转 cs 插件及序列化与反序列化),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 添加 dll

1. 下载 protobuf 源码

根据需要下载 protobuf 指定版本的源码,这里以 v3.21.12(protobuf-csharp-3.21.12.zip)为例:

下载地址:「https://github.com/protocolbuffers/protobuf/releases」

2. 下载 Visual Studio 2022

曾尝试使用 Visual Studio 2021 版本编译,但是会报错,更新版本后,即可编译成功

下载地址:「https://visualstudio.microsoft.com/zh-hans/downloads/」

3. 编译 dll

1. 使用 Visual Studio 2022 打开 protobuf 项目中的 Google.Protobuf.sln

2. 编译模式选择:Release

3. Google.Protobuf 右键选择生成 Google.Protobuf

4. 拷贝 dll

编译生成的 dll 在 csharp/src/Google.Protobuf/bin/Release 目录下

将 net45 目录下所有的 dll 文件拷贝到 Unity 指定目录中

2. proto 转 cs

1. 下载编译器

在 protobuf 源码链接中下载对应的平台的编译器(mac: protoc-21.12-osx-x86_64.zip,windows:protoc-21.12-win64.zip)

2. 命令行转换

在终端中进入到编译器所在的目录:bin/protoc,然后执行对应的命令

  • 转换指定 proto 文件:

./protoc ./Addressbook.proto --csharp_out=./
  • 转换指定目录下所有 proto 文件:

./protoc ./*.proto --csharp_out=./

将生成的 cs 文件,放入 Unity 项目中

3. 插件转换

除了直接使用命令行外,也可以在 Unity 中编写插件,利用 Process 执行命令行,转换 proto 文件:

public class ProtoToClass
{[MenuItem("RavenKit/Proto To Class")]public static void GenerateClassFromProto(){string rootPath = Environment.CurrentDirectory;string protoPath = Path.Combine(rootPath, "Proto/");string protoc = Path.Combine(protoPath,RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "protoc.exe" : "protoc");string outPath = EditorPrefs.GetString(Application.identifier + "-ProtoClassPath");if (string.IsNullOrEmpty(outPath)){outPath = EditorUtility.OpenFolderPanel("选择存储目录", Application.dataPath, "");if (!string.IsNullOrEmpty(outPath)){EditorPrefs.SetString(Application.identifier + "-ProtoClassPath", outPath);}}string[] protoFiles = Directory.GetFiles(protoPath, "*.proto");foreach (var variable in protoFiles){string argument = $"--csharp_out={outPath} --proto_path={protoPath} {variable}";Run(protoc, argument);}AssetDatabase.Refresh();}public static Process Run(string exe, string arguments){ProcessStartInfo info = new ProcessStartInfo{FileName = exe,Arguments = arguments,CreateNoWindow = true,UseShellExecute = false,RedirectStandardOutput = true,RedirectStandardError = true,};Process process = Process.Start(info);process.WaitForExit();if (process.ExitCode != 0){Debug.LogError($"Failed to Run {arguments}. Exit code: " + process.ExitCode);}return process;}
}

3. 序列化及反序列化

使用方法在官方的源码中也有详细的示例:

byte[] bytes;
// Create a new person
Person person = new Person
{Id = 1,Name = "Foo",Email = "foo@bar",Phones = { new Person.Types.PhoneNumber { Number = "555-1212" } }
};
using (MemoryStream stream = new MemoryStream())
{// Save the person to a streamperson.WriteTo(stream);bytes = stream.ToArray();
}
Person copy = Person.Parser.ParseFrom(bytes);AddressBook book = new AddressBook
{People = { copy }
};
bytes = book.ToByteArray();
// And read the address book back again
AddressBook restored = AddressBook.Parser.ParseFrom(bytes);// The message performs a deep-comparison on equality:
if (restored.People.Count != 1 || !person.Equals(restored.People[0]))
{throw new Exception("There is a bad person in here!");
}

反序列化时,除了使用 ParseFrom 方法

AddressBook.Parser.ParseFrom(bytes) 

也可以使用 MergeFrom 方法

message.MergeFrom(data);

将序列化和反序列化封装为通用的函数:

public static class ProtobufUtility
{/// <summary>/// 序列化/// </summary>/// <param name="msg"></param>/// <returns></returns>public static byte[] Serialize(IMessage message){using (MemoryStream stream = new MemoryStream()){message.WriteTo(stream);byte[] result = ms.ToArray();return result;}}/// <summary>/// 反序列化/// </summary>/// <typeparam name="T"></typeparam>/// <param name="data"></param>/// <returns></returns>public static T Deserialize<T>(byte[] data) where T : IMessage, new(){T message = new T();// message = (T)message.Descriptor.Parser.ParseFrom(data);message.MergeFrom(data);return msg;}
}

这篇关于Unity | 集成 Protobuf(proto 转 cs 插件及序列化与反序列化)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/935420

相关文章

Maven 插件配置分层架构深度解析

《Maven插件配置分层架构深度解析》:本文主要介绍Maven插件配置分层架构深度解析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Maven 插件配置分层架构深度解析引言:当构建逻辑遇上复杂配置第一章 Maven插件配置的三重境界1.1 插件配置的拓扑

Spring Boot集成SLF4j从基础到高级实践(最新推荐)

《SpringBoot集成SLF4j从基础到高级实践(最新推荐)》SLF4j(SimpleLoggingFacadeforJava)是一个日志门面(Facade),不是具体的日志实现,这篇文章主要介... 目录一、日志框架概述与SLF4j简介1.1 为什么需要日志框架1.2 主流日志框架对比1.3 SLF4

Spring Boot集成Logback终极指南之从基础到高级配置实战指南

《SpringBoot集成Logback终极指南之从基础到高级配置实战指南》Logback是一个可靠、通用且快速的Java日志框架,作为Log4j的继承者,由Log4j创始人设计,:本文主要介绍... 目录一、Logback简介与Spring Boot集成基础1.1 Logback是什么?1.2 Sprin

Idea插件MybatisX失效的问题解决

《Idea插件MybatisX失效的问题解决》:本文主要介绍Idea插件MybatisX失效的问题解决,详细的介绍了4种问题的解决方法,具有一定的参考价值,感兴趣的可以了解一下... 目录一、重启idea或者卸载重装MyBATis插件(无需多言)二、检查.XML文件与.Java(该文件后缀Idea可能会隐藏

springboot集成Lucene的详细指南

《springboot集成Lucene的详细指南》这篇文章主要为大家详细介绍了springboot集成Lucene的详细指南,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起... 目录添加依赖创建配置类创建实体类创建索引服务类创建搜索服务类创建控制器类使用示例以下是 Spring

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

Spring Boot 集成 Quartz并使用Cron 表达式实现定时任务

《SpringBoot集成Quartz并使用Cron表达式实现定时任务》本篇文章介绍了如何在SpringBoot中集成Quartz进行定时任务调度,并通过Cron表达式控制任务... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启动 Sprin

SpringBoot集成Milvus实现数据增删改查功能

《SpringBoot集成Milvus实现数据增删改查功能》milvus支持的语言比较多,支持python,Java,Go,node等开发语言,本文主要介绍如何使用Java语言,采用springboo... 目录1、Milvus基本概念2、添加maven依赖3、配置yml文件4、创建MilvusClient

如何配置Spring Boot中的Jackson序列化

《如何配置SpringBoot中的Jackson序列化》在开发基于SpringBoot的应用程序时,Jackson是默认的JSON序列化和反序列化工具,本文将详细介绍如何在SpringBoot中配置... 目录配置Spring Boot中的Jackson序列化1. 为什么需要自定义Jackson配置?2.