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 stream
    person.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;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/578642.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

防火墙技术基础篇:认识安全策略、安全区域、域间转发及报文转发流程

防火墙技术基础篇&#xff1a;认识安全策略、安全区域、域间转发及报文转发流程 一、安全策略匹配机制 简单通俗的讲&#xff0c;防火墙设备最基本的用途就是定义数据如何转发&#xff0c;靠什么定义呢&#xff1f;最基本的就是安全策略&#xff0c;当流量来到防火墙之后首先…

组播技术原理概述

组播与广播和单播的对比 l 组播、广播和单播工作模式的对比 单播&#xff1a;数据报文从一台主机&#xff0c;点对点的发给另外一台主机 广播&#xff1a;数据报文从一台主机&#xff0c;发给广播域内的全部主机 组播&#xff1a;数据报文从一台主机&#xff0c;发给…

JS----前端将列表数据转树型数据

前端将列表数据转树型数据 场景&#xff1a;后端返回列表数据&#xff0c;由前端根据业务需求完成树型数据转换&#xff0c; 常用于侧边导航菜单&#xff0c;下拉树型数据项等 export function listToTree(data: []) {var map: any {},tree: any []data.forEach((item: any…

ansible-playbook获取当前执行任务的ip及hostname

目录 概述注意实践代码 概述 注意 此问题&#xff0c;配置上一个文件即可解决 实践 代码 --- - name: Get IP Addresshosts: allgather_facts: notasks:- name: Get IP Addressansible.builtin.setup:register: host_ip- name: Print IP Addressansible.builtin.debug:msg:…

网络程序 -- TCP版服务器

一 多进程版TCP服务器 1.1 核心功能 对于之前编写的 字符串回响程序 来说&#xff0c;如果只有一个客户端进行连接并通信&#xff0c;是没有问题的&#xff0c;但如果有多个客户端发起连接请求&#xff0c;并尝试进行通信&#xff0c;服务器是无法应对的 原因在于 服务器是一个…

数据结构 - 队列 [动画+代码注释超详解],萌新轻松上手!!!

一. 队列的概念 队列是一种特殊的线性表&#xff0c;用于存储元素&#xff0c;并且按照先进先出(First In First Out)的顺序进行管理&#xff0c;这意味着最先加入队列的元素将会是最先从队列中被移除的元素 队列的原型&#xff1a;只允许在一端进行插入数据的操作&#xff0c…

【嵌入式AI开发】轻量级卷积神经网络MobileNetV2详解

前言:MobileNetV2网络先升维后降维,在降维时使用线性激活函数,带残差的Inverted bottleck模块,防止ReLU信息丢失。在图像分类、目标检测、语义分割等任务上实现了网络轻量化、速度和准确度的权衡。 回顾MobileNetV1的理论和MobileNetV2项目实战可查阅如下链接: 【嵌入式AI…

使用SDRPI运行openwifi和设置网口

目录 一 制作启动盘 二 使用串口的方式启动openwifi 三 无线连接 四 网口设置&#xff0c;有线连接 五 使用SSH登录 一 制作启动盘 在github上下载img文件&#xff0c;由于github上下载速度比较慢&#xff0c;我会上传网盘链接 githun下载img文件地址: https://git…

OS对软件的管理,进程,PCB、子进程

进程 可执行程序加载到内存中&#xff0c;操作系统为内个程序都形成一个PCB对象&#xff08;结构体对象&#xff09;&#xff0c;PCB里存放着这个程序的所有的属性。进程可执行程序PCB &#xff0c;CPU执行程序也是先通过该程序的PCB找到相应的程序代码&#xff0c;然后一条一…

SpringCloud之Hystrix

Hystrix理解 熔断器本身是一种开关装置&#xff0c;用于在电路上保护线路过载。当线路中有电器发生短路时&#xff0c;熔断器能够及时切断故障电路&#xff0c;防止发生过载、发热甚至起火等严重后果。这种保护机制被借鉴到分布式系统的设计中&#xff0c;形成了类似Hystrix中…

基于SpringBoot+Vue校园二手交易系统的设计与实现

系统介绍 自从新冠疫情爆发以来&#xff0c;各个线下实体越来越难做&#xff0c;线下购物的人也越来越少&#xff0c;随之带来的是一些不必要的浪费&#xff0c;尤其是即将毕业的大学生&#xff0c;各种用品不方便携带走导致被遗弃&#xff0c;造成大量的浪费。本系统目的就是让…

安装好fedora_kde系统后的操作

文章目录 1 前言2 办公软件2.1 输入法2.1.1 安装 fcitx52.1.2 安装 fcitx5-rime2.1.3 安装 東風破2.1.4 使用 東風破 安装 郭斌勇 大神的 新世纪五笔 项目2.1.5 配置 fcitx5-rime2.1.6 重新部署 3 感谢阅读~ 1 前言 本文用的是 fedora 40 kde plasma 6。 因为有很多的软件都同时…

2024全国大学生高新技术竞赛——算法智星挑战赛(A~J)

好多都是之前的原题&#xff0c;甚至有上次第二届全国大学生信息技术认证挑战赛的原题&#xff0c;刚打完又来一遍&#xff0c;没绷住。 A. 手机 原题之一&#xff0c;具体出处忘了 最无脑的方法直接用map记录每个按下的值就行了&#xff0c;代码仅供参考。 #include <bit…

MATLAB矩阵

MATLAB 矩阵 矩阵是数字的二维数组。 在MATLAB中&#xff0c;您可以通过在每行中以逗号或空格分隔的数字输入元素并使用分号标记每行的结尾来创建矩阵。 例如&#xff0c;让我们创建一个45矩阵一- 示例 a [ 1 2 3 4 5; 2 3 4 5 6; 3 4 5 6 7; 4 5 6 7 8] MATLAB将执行上述语…

pycharm使用ssh连接服务器

1、具体流程 打开pycharm – File – Setting 输入服务器的IP地址&#xff0c;端口号、登录账号名 输入登陆账号的密码 下一步 一些初级设置 2、一些需要注意的小问题 2.1 更改代码地址 2.2 本地代码上传到服务器 首先在需要上传文件右键 2.3 在服务器的环境中上新安装库&am…

Docker 简单使用及安装常用软件

一、Docker 安装、配置与卸载 1.1、Docker 安装 # 1.安装gcc环境 yum -y install gcc gcc-c && \# 2. 卸载docker旧版本&#xff08;可能之前有安装&#xff09; yum -y remove docker docker-common docker-selinux docker-engine && \# 3. 安装依赖的软件包…

【项目学习01_2024.04.27_Day01】

学习笔记 项目学习链接第2章 内容管理模块v3.11 模块需求分析1.1 什么是需求分析1.2 模块介绍1.3 业务流程1.4 界面原型 2 创建模块工程2.1 模块工程结构父工程和子工程之间的继承关系以及工程与工程之间的依赖关系&#xff0c;通俗理解&#xff1a;2.2 创建模块工程\pom\含义及…

go 安装软件报go.mod file not found

执行 go get -u github.com/go-sql-driver/mysql 下载mysql 报错 解决方法: 控制台&#xff1a;输入go env 返回如下&#xff1a; 红圈值为NUL&#xff0c;需要设置GOMOD的值, 然后再控制台执行 &#xff08;1&#xff09;mkdir mod (2)go mod init mod 然后再执行下载&…

AIGC——什么是人工智能生成内容

人工智能生成内容&#xff08;AIGC&#xff09;是当今数字时代的一个引人注目的前沿技术&#xff0c;它借助深度学习和自然语言处理等技术&#xff0c;使计算机系统具备了生成高质量文本、图像、音频等多媒体内容的能力。AIGC的出现不仅推动了信息技术的发展&#xff0c;也在多…

【匹配】匈牙利匹配算法

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 匈牙利匹配算法 1. 正文 1.1 基础概念 二分图 顶点分为两个集合&#xff0c;集合间顶点相连&#xff0c;集合内点不相连 匹配 一个匹配就是一个边的…