unity 中使用Google Protobuf的使用

准备工作

unity 2019.4.x
Protobuff 3.20.3

Protobuf是用来干什么的?

Protobuf是Protocol Buffers的简称,它是Google公司开发的一种数据描述语言,是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化 。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。proto2中提供了 C++、Java、Python 三种语言的 API。在proto3中支持所有的语言!

主要用于(数据)通信协议、数据存储等。

Protobuf的优势

Protobuf 有如 XML和Json,不过它更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构。只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言或从各种不同数据流中对你的结构化数据轻松读写。

它有一个非常棒的特性,即“向后”兼容性好,人们不必破坏已部署的、依靠“老”数据格式的程序就可以对数据结构进行升级。这样您的程序就可以不必担心因为消息结构的改变而造成的大规模的代码重构或者迁移的问题。因为添加新的消息中的 field 并不会引起已经发布的程序的任何改变。

Protobuf 语义更清晰,无需类似 XML 解析器的东西(因为 Protobuf 编译器会将 .proto 文件编译生成对应的数据访问类以对 Protobuf 数据进行序列化、反序列化操作)。

使用 Protobuf 无需学习复杂的文档对象模型,Protobuf 的编程模式比较友好,简单易学,同时它拥有良好的文档和示例,对于喜欢简单事物的人们而言,Protobuf 比其他的技术更加有吸引力。

下载与安装

这里下载3.20.3
Google Protobuff下载

在这里插入图片描述
在这里插入图片描述
下载好之后解压到你的固定文件夹里!

主要基础类型(其他可以自行查阅)

.proto类型 java类型 C++类型 备注
double double double
float float float
int32 int int32 使用可边长编码方式。编码负数时不够高效,如果该字段可能有负数,用sint32
sint32 long int32 使用可边长编码方式。有符号的整型值。编码时比int32高效
sint64 long int64 使用可边长编码方式。有符号的整型值。编码时比int62高效
string String string 一个字符串必须时UTF8或7-bit ASCII编码文本
bool boolean bool

特殊字段

英文 中文 备注
enum 枚举(数字从零开始)作用时为字段指定某“一定义值序列” enum Sex{Man=0;Women=1}
message 消息体,C#中的class messge User{}
repeated 数组或集合 ,C# List OR [ ] repeated User user= 0
// 注释 //此处为注释
extend 扩展 extend User{}
package 包名 C#中的命名空间,防止命名冲突

编写.proto文件

我们在刚才解压的文件夹里找到bin文件夹
在这里插入图片描述新建txt文本取名Person.proto,切记后缀.txt改为.proto
输入一下代码

syntax="proto3";//指定了正在使用proto3语法,如果没指定编译器默认使用proto2语法
package TestGoogleProtoBuff;//等于C#中命名空间

message personInfo
{
	string name=1;
	int32 age=2;
	int64 money=3;
	message PhoneNumber{
		string number=1;
		PhoneType type=2;
	}
	repeated PhoneNumber phone=5;
}

enum PhoneType{
	HOME=0;
	WORK=1;
	MOBILE=2;
}

然后在这个文件夹中创建ExProtProto.bat,输入一下命令并保存。

在这里插入图片描述
双击ExProtProto.bat,我们发现生成了Person.cs文件
在这里插入图片描述

Unity中的使用

然后我们打开unity,新建文件夹Proto,将刚刚生成好的Person.cs代码放在Proto文件夹中。

在这里插入图片描述
此时unity控制台会大量飘红!这时因为缺少了Person.cs的引用所导致的。
我们用vs打开Person.cs,点击最上面菜单栏 工具>NuGet 包管理器>管理解决方案的NuGet 管理包
在这里插入图片描述
版本一定要选择咱们一开始下载的对应版本否则不兼容!这里选择3.20.3。然后点击安装,稍等安装好之后我们打开unity项目根目录。
在这里插入图片描述

分别把
.\Packages\Google.Protobuf.3.20.3\lib\netstandard2.0\Google.Protobuf.dll
.\Packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll
.\Packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll
.\Packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
这几个dll文件放在Assets/Plugins文件夹中,等待unity重新编译,然后清空控制台错误消除。

注意:这里选择netstandard2.0中的dll文件是因为unity2019.4.x中 api版本对应的时.NET Standard 2.0,不同版本的unity要找不同的net版本对应,否则会有冲突,一般更高版本的unityapi版本为netstandard2.1
在这里插入图片描述

在这里插入图片描述

然后开始别写序列化和反序列化工具,其实类似于大家熟悉的Json,在网络通讯中前端把实体对象数据通过序列化成Json格式的字符串传给后端,然后收到的后端数据在反序列化成前端能使用的对象。注意proto会将实例序列化成2进制的数据格式!

我们在unity中新建ProtoBufffer.cs脚本

using Google.Protobuf;
public class ProtoBufffer
{
    
    
    public static byte[] Serialize(IMessage message)
    {
    
    
        return message.ToByteArray();
    }

    public static T DeSerialize<T>(byte[] packet)where T:IMessage, new()
    {
    
    
        IMessage message = new T();
        try
        {
    
    
            return (T)message.Descriptor.Parser.ParseFrom(packet);
        }
        catch (System.Exception e)
        {
    
    
            throw;
        }
    }
}

在创建一个Test.cs脚本来测试该功能,将该脚本拖到主摄像机上。

using TestGoogleProtoBuff;
using UnityEngine;

public class Test : MonoBehaviour
{
    
    
    // Start is called before the first frame update
    void Start()
    {
    
    
        personInfo info = new personInfo();
        info.Name = "ys";
        info.Age = 50;
        info.Money = 9999;
        info.Phone.Add(new personInfo.Types.PhoneNumber {
    
     Number = "12123",Type=PhoneType.Home});
        byte[] msg = ProtoBufffer.Serialize(info);
        Debug.Log(msg.Length);

        personInfo deinfo  = ProtoBufffer.DeSerialize<personInfo>(msg);
        Debug.Log("姓名:"+deinfo.Name);
        Debug.Log("年龄:"+deinfo.Age);
        Debug.Log("资产:" + deinfo.Money);
        Debug.Log($"{
      
      deinfo.Phone[0].Type}的电话号:{
      
      deinfo.Phone[0].Number}");
    }
}

运行unity,查看控制台消息。序列化与反序列化成功!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43298513/article/details/135462197