Unity中为什么使用protobuf以及使用方法

Unity中使用ProtoBuf-保姆式教程 写好 proto 文件之后用 protoc. 编译器将.proto文件编译成目标语言。 阅读详情

转自:http://blog.youkuaiyun.com/panda_bear/article/details/9949751

在移动手机游戏开发中,目前Unity3D已成为比较主流的开发技术。

那么对于客户端服务器协议的打解包,我们有3中常用的处理方式:

1、自定义结构体:在协议中直接传输代码中自定义的结构体;这种方式的坏处是极大的增加了重复性的工作量,并且不能实现协议前后向兼容,可扩展性差;

2、json、xml等文本协议格式: 使用json、xml等文本协议作为协议格式;这种方式的好处是易于开发,方便协议前后向兼容和扩展,缺点是不能序列化,数据量大,浪费带宽;

3、推荐使用的方式: protobuf协议打解包方式;protobuf是google提出的一套开源协议,具有良好的前后向协议兼容性,易于扩展,并且具有很高的序列化和反序列化的效率,能极大的减小传输数据量的大小;

在Unity3D开发中,对于网络部分一般使用C#语言进行开发。一般推荐使用protobuf-net第三方库来进行开发。

但是不幸的是,其中使用到的JIT技术在Unity3D的IOS版本中是不能使用的,在序列化时会导致异常。

经过google网上搜索,找到一种不方便使用的解决方案如下:

http://www.frictionpointstudios.com/blog/2011/3/31/using-protobuf-net-serialization-in-unity-iphone.html

但是该方案很复杂,非常不便于操作。

经过笔者自己的实验,探索出下面可用的一种解决方案:

1、从SVN上下载protbuf-net的源码:

http://protobuf-net.googlecode.com/svn/trunk/protobuf-net

2、将该目录中的所有C#源码拷贝到Unity3D中,直接使用源码而不是第三方dll;

3、此时在Unity中编译时,可能会报错说 unsafe不能使用;

4、采用如下方案可以解决: 在Assets目录下面新建 smcs.rsp文件,并在其中写入  -unsafe 字符串,前后不加空格;

5、重新启动unity,此时我们可以发现该工程能够通过编译;


经验证,该方案在IOS设备上也是可用的。从而保证我们的protobuf能够应用在Unity移动开发中。


下面是更为详细的使用方法:

转自     http://my.oschina.net/faint/blog/296785


第一部分 dll

1 下面大多数内容,都是使用c#编译的dll来实现的。

2 编译为dll后,要拖放到unity3d的Assets里面,才能using到。

3 有以下类似错误,就是使用了非.net 2.0编译的dll。注意项目必须是在.net 2.0版本编译的才能正常在unity3d当中使用。

Unhandled Exception: System.TypeLoadException: Could not load type 'System.Runtime.Versioning.TargetFrameworkAttribute' from assembly 'MyModel'

4 应该不能用MonoDevelop编译下面会提到的Serializer部分(编译不出dll,会报错)。需用vs编译。


第二部分 tcp/ip

?
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
using  System;
using  System.IO;
using  System.Net.Sockets;
 
namespace  TcpConnector{
 
     public  struct  Msg {
         public  int  Type;
         public  int  Size;
         public  byte [] Content;
     }
 
     public  class  Connector{
 
         const  int  HEAD_SIZE = 4;
         private  TcpClient client;
         NetworkStream stream;
 
         public  bool  Connect( string  ip, int  port){
             try {
                 client =   new  TcpClient(ip,port);
                 stream = client.GetStream();
                 return  true ;
             }
             catch {
                 return  false ;
             }
         }
 
         public  void  Disconnect(){
             stream.Close();
             client.Close();
         }
 
         private  int  readType(){
             byte [] headData =  new  byte [HEAD_SIZE];
             stream.Read(headData,0,headData.Length);
 
             int  msgType = BitConverter.ToInt32(headData,0);
             return  msgType;
         }
 
         private  int  readSize(){
             byte [] headData =  new  byte [HEAD_SIZE];
             stream.Read(headData,0,headData.Length);
 
             int  msgSize = BitConverter.ToInt32(headData,0);
             return  msgSize;
         }
 
         private  byte [] readContent( int  leghth){
             byte [] content =  new  byte [leghth];
             stream.Read(content,0,content.Length);
             return  content;
         }
 
         public  Msg Read(){
             Msg msg =  new  Msg();
             msg.Type = readType();
             msg.Size = readSize();
 
             if  (msg.Size > 0) {
                 msg.Content = readContent(msg.Size);
             }
             return  msg;
         }
 
         public  void  Write( int  msgType, byte [] msgContent){
             byte [] msgTypeByte = BitConverter.GetBytes(msgType);
             int  msgSize = msgContent.Length;
             byte [] msgSizeByte = BitConverter.GetBytes(msgSize);
  
             int  totalSize = HEAD_SIZE + HEAD_SIZE + msgSize;
             byte [] msgByte =  new  byte [totalSize];
  
             int  index = 0;
             for  ( int  i = 0; i < HEAD_SIZE; i++){  // put msg type
                 if  (msgTypeByte.Length > i){
                     msgByte[index] = msgTypeByte[i];
                 }
                 index++;
             }
  
  
             for  ( int  i = 0; i < HEAD_SIZE; i++){  // put msg size
                 if  (msgTypeByte.Length > i){
                     msgByte[index + i] = msgSizeByte[i];
                 }
                 index++;
             }
  
             for  ( int  i = 0; i < msgSize; i++){  // put msg content
                 if  (msgTypeByte.Length>i){
                     msgByte[index + i] = msgContent[i];
                 }
                 index++;
             }
  
             stream.Write(msgByte,0,msgByte.Length);
             stream.Flush();
         }
     }
}


主要用的是TcpClient,NetworkStream,BitConverter.

?
1
2
3
4
5
6
7
8
9
TcpClient client =  new  TcpClient(ip,port);  // 获取与服务器连接
NetworkStream stream = client.GetStream();  // 获取连接的流
stream.Read(buf,0,lenght);  // 读取至buf
stream.Write(buf,0,lenght);  // 写至buf
BitConverter.GetBytes(data);  // 用于将整数转为字节
BitConverter.ToInt32(data,0);  // 用于将字节转为整数
stream.Flush();  // 将流中缓存发出,而不等候
stream.Close();  // 关闭流
client.Close();  // 关闭连接


第三部分 protobuf-net

翻墙下载安装:http://code.google.com/p/protobuf-net/

数据结构编译成dll:

先新建解决方案,新建库,添加下载的full/unity/dll。具体代码如下:

?
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
using  System;
using  ProtoBuf;
 
namespace  CSProtoData
{
     [ProtoContract]
     public  class  Head
     {
         [ProtoMember(1)]
         public  Int32 DataType {  get ;  set ; }
         [ProtoMember(2)]
         public  Int64 DataDate {  get ;  set ; }
         [ProtoMember(3)]
         public  byte [] DataContent {  get ;  set ; }
     }
 
     [ProtoContract]
     public  class  Number
     {
         [ProtoMember(1)]
         public  Int32 Index {  get ;  set ; }
         [ProtoMember(2)]
         public  Int64 Value {  get ;  set ; }
     }
 
     public  class  Board
     {
         [ProtoMember(1)]
         public  Int64 Rank {  get ;  set ; }
         [ProtoMember(2)]
         public  string  TargetName {  get ;  set ; }
         [ProtoMember(3)]
         public  Int64 Number {  get ;  set ; }
     }
 
     public  class  Request
     {
         [ProtoMember(1)]
         public  string  DataType {  get ;  set ; }
         [ProtoMember(2)]
         public  Int64 DataDate {  get ;  set ; }
         [ProtoMember(3)]
         public  Int32 Start {  get ;  set ; }
         [ProtoMember(4)]
         public  Int32 End {  get ;  set ; }
     }
}

编译完后,生成dll下面马上用到(同时也要拖放到unity/assets下)。


第三部分 下

因为protobuf-net的序列化和反序列化用的是jit,ios不支持jit,所以需采用编译成dll的方式来解决问题:

vs中,新建命令行程序,添加protobuf-net/full/unity/dll,添加刚生成的dll,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using  System;
using  ProtoBuf;
using  ProtoSerializer;
using  CSProtoData;
 
namespace  ProtoSerializer
{
     class  MainClass
     {
         public  static  void  Main( string [] args)
         {
             var  model = ProtoBuf.Meta.TypeModel.Create();
 
             model.Add( typeof (Head),  true );
             model.Add( typeof (Number),  true );
             model.Add( typeof (Board),  true );
             model.Add( typeof (Request),  true );
 
             model.Compile( "CSProtoSerializer" ,  "CSProtoSerializer.dll" );
         }
     }
}

这里按运行后,会在目录下生成:CSProtoSerializer.dll,一样拖放到unity/assets下。

其中typeof()的,就是proto数据类型,在上半部分有定义的内容。


第四部分 unity代码

执行完以上步骤,unity/assets下应该有这么几个dll:

protobuf-net/full/unity/dll

proto的data的dll(第三部分)

data的序列化的dll(第三部分下,运行后生成的那个)

还有用于tcp连接的dll(第二部分)

那么实际在unity当中调用的代码则是:

?
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
using  UnityEngine;
using  System.Collections;
using  TcpConnector;
using  ProtoBuf;
using  CSProtoData;
using  System.IO;
 
public  class  testTcp : MonoBehaviour {
 
     // Use this for initialization
     void  Start () {
         Connector conn =  new  Connector();
         bool  result = conn.Connect( "127.0.0.1" ,17093);
         Debug.Log(result);
 
         Head head= new  Head{};
         head.DataType = 2;
         head.DataDate = 201407312;
 
         MemoryStream memStream =  new  MemoryStream();
         ProtoBuf.Serializer.Serialize<CSProtoData.Head>(memStream, head);
         byte [] x = memStream.ToArray();
 
         conn.Write(1,x);
         conn.Write(1,x);
     }
     
     // Update is called once per frame
     void  Update () {
         
     }
}


新建个script,随便挂在比如camara的组件里即可。


也不知道这到底行不行,到真正工作中再验证一下了。


在Unity中使用Protobuf进行序列化 保姆级教程,一步一步教你如何在Unity中使用Protobuf对数据进行序列化和反序列化 阅读详情

相关推荐

unity 中使用Google Protobuf的使用

在proto3中支持所有的语言!注意:这里选择netstandard2.0中的dll文件是因为unity2019.4.x中 api版本对应的时.NET Standard 2.0,不同版本的unity要找不同的net版本对应,否则会有冲突,一般更高版本的unityapi版本为netstandard2.1。使用 Protobuf 无需学习复杂的文档对象模型,Protobuf 的编程模式比较友好,简单易学,同时它拥有良好的文档和示例,对于喜欢简单事物的人们而言,Protobuf 比其他的技术更加有吸引力。

weixin_43298513的博客 3529

Unity 谷歌的Protobuf数据协议

<p> <img src="https://img-bss.youkuaiyun.com/201909110221081694.png" alt="" /> </p>

Unity中使用Protobuf-net

使用Protobuf的好处我就不说了,这里强调使用。(目前我认为是为了实现C++服务器与unity的C#之间的跨平台通信) 首先从gitHub上下载源码   https://github.com/mgravell/protobuf-net 然后进入如下目录下 点击.csproj,进入工程  编译一下,得到如下图: 把protobuf-net.dll加入到 打开该目录下的.

无道的博客 3884

Unity开发---ProtoBuf

protocol buffers 是google公司开发的一种数据描述语言 ,可以将结构化数据进行序列化,可用于数据存储、通讯协议等方面,具有高效,可扩展性强,文件小,传输快,支持多种编程语言等特点,缺点就是没有阅读性。

南宫铭的博客 2582

Unity中使用Protobuf 来传输消息

其实说白了,probuf’用于前后端通信的时候就是通过规定的语法内容来进行二进制的一些数据处理,这样比利用json和xml传输效率要高一点,可能第一次接触这个东西有点不太懂,但是公司中既然使用了protobuf这种数据交换格式,肯定会有一套成熟的机制来处理这些文件的,但是一定要明白如何定制消息,发送消息,然后服务器会给我们的是什么样子的内容,搞清楚了这些东西后,管他用什么来传输呢。协议号的作用就是用来确定用于解析数据的解析类,所以也可以称为协议类型名,可以是string和int类型的数据。

*LYZY*的博客 3606

GD32F303 ADC+DMA实战:用硬件过采样搞定多通道数据采集(附完整代码)

本文详细介绍了GD32F303系列MCU通过ADC+DMA结合硬件过采样技术实现多通道数据采集的实战方案。从硬件设计要点到软件配置全解析,包括时钟树配置、ADC模块初始化和DMA传输设置,提供了完整的代码示例和优化技巧,帮助工程师构建高精度、低功耗的数据采集系统。

weixin_30466039的博客 318

Unity使用ProtoBuf

由Google开发的一种语言中立、平台中立、可扩展的序列化结构数据的方式。protobuf-net 是一个用于 .NET 平台的 Protocol Buffers 实现库。protobuf-net 完全遵循 Protocol Buffers 的序列化格式规范,因此它可以与任何其他实现 Protocol Buffers 的库(如 Java、Python、C++ 等)进行互操作。

飞浪纪元FE的博客 3260

4. PCIe 接口时序

在上一篇中,大致介绍IPcore接口。总的来说接口如下图数据的接收和发送通过transmitTLPinterface和ReceiveTLPinterface。收发数据的时序也只是描述这几个接口的关系。从手册上截取PCIex1的接口时序。

jjinl的专栏 6122

unity中使用Protobuf

在unity中简单使用protobuf进行序列化和反序列化

qq_20454705的博客 6297

iTunes登录协议逆向与自动化实现

本文详细解析了iTunes登录协议的逆向工程与自动化实现方法,涵盖请求体构造、签名生成和会话管理等关键技术。通过XML结构解析、X-Apple-ActionSignature生成原理及完整登录流程实现,帮助开发者高效完成iTunes自动化登录,提升工作效率。

weixin_26938645的博客 939

[模型部署]-[LLM]昇腾部署Qwen3-Coder-30B-A3B-Instruct

摘要:本文介绍了在Ascend NPU上部署Qwen3-Coder-30B-A3B-Instruct大模型的实践过程。通过vLLM-Ascend框架,详细说明了环境准备(CANN 8.1、PyTorch-NPU 2.5.1等)、模型下载、容器启动及服务部署步骤,包括vLLM服务的启动参数配置和接口测试方法。测试结果显示在当前2卡910B3配置下性能表现仅为8token/s(1并发),并指出流式调用时存在无法输出usage信息的问题。该方案为Ascend平台私有化部署大模型推理服务提供了参考实现。

1670

Protobuf 在Unity中的使用

Protobuf在Unity中的序列化与反序列化

司军礼的博客 9347

一分钟了解 “提示词工程”、“上下文工程”、“驾驭工程”

在大模型刚刚进入大众视野的初期,开发者面临的最大挑战是如何让模型听懂人类的指令。这一阶段被称为提示词工程时代。其核心思想非常直观:通过精心设计输入的文本提示,引导模型输出符合预期的结果。这一时期的开发者更像是“提示词巫师”,他们热衷于寻找所谓的“魔法咒语”。典型的技巧包括角色设定、思维链、少样本学习以及输出格式约束。例如,仅仅在问题前加上一句“请一步步思考”,模型的推理能力往往就能得到显著提升。然而,随着应用场景的复杂化,提示词工程的局限性逐渐暴露。

h a 6 6 6 c k 为 你解决复杂难题! 568

Unity中Protobuf的使用

前几天,公司前辈要我去学习一下protobuf在unity中的使用,因为序列化的问题在网上找了很多教程终于将问题解决,特此记录一下代码和使用情况。 首先找到protobuf-net,Google.Protobuf两个拓展文件导入到unity中通过using ProtoBuf就可以正常使用了,使用有两个方法。 第一种是使用protoc.exe工具将.pr...

顽皮细雨的博客 1899

R语言机器学习:XGBoost线性回归模型的SHAP值

SHAP(SHapley Additive exPlanations)值是一种基于博弈论Shapley值的机器学习模型解释方法,能够解释任何模型的预测结果。其主要用途包括:1)提高模型的可解释性,帮助非技术用户理解模型预测;2)识别对模型预测最重要的特征,辅助特征选择;3)调试模型,发现预测中的异常;4)评估模型公平性,避免偏见。SHAP值的计算方法包括初始化、迭代计算、归一化和解释,常用工具如Python的shap库支持多种计算方式(如TreeSHAP、KernelSHAP等)。本文还提供了基于R语言计算

专注生信领域 3441

【定制功能】LVGL 页面管理

页面管理的主要针对实际复杂的UI项目的。支持多页面管理,包含页面跳转和返回(主要是方便项目功能管理)支持后台页面自动销毁、前台页面自动创建(主要是节约资源使用)支持语言切换逻辑(页面重建功能)支持主题切换逻辑支持页面切换动画效果首先,页面管理是针对act_src图层来讲的。仅在screens数组中供act_src切换的对象树才会被此页面管理功能所管理。这意味着,如果top_layer或者sys_layer图层上,有页面需要重建时,需要特殊处理(实际项目中top_layer或者。

Bigan(安)的博客 5751

unity使用Google Protobuf

看到网上说Google的这个序列化工具能自动生成脚本(java、c#、c++。。。。。。)感觉很厉害的样子,于是就学学怎么在unity里用,正好结合之前写的socket通信,做一个demo。我看网上protobuf的教程很乱啊,最开始想找一篇跟着做下来完事了,结果坑也是不少。。。。。。 1.打开vs新建一个c#控制台工程 2.管理解决方案的nuget包 3.搜索Google protobuf ...

带酒书生的博客 2063

matlab电子科技大学数学实验期末模拟35道(1)

【代码】matlab电子科技大学数学实验期末模拟35道。

c_wrj_的博客 2043

Unity如何使用Protobuf

Unity版本:2018.4.17 Protobuf版本:3.4 (下载地址) Protobuf是一种高效轻便的数据格式,跟平台和语言无关,在网络通信和数据存储中应用非常广泛。 Unity中使用需要按照Protobuf的语法规范,先定义好Proto文件,然后用Protobuf官方工具把Proto文件转换成C#文件,再把该C#文件和Protobuf库文件导入到Unity中就可以用了。 定义Pro...

楚游香的博客 1329

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

关于Unity使用Protobuf

为了优化一下协议传输,准备使用protobuf来作为协议。 服务器端: 服务器端都好说,因为是C#所以直接下载NuGet包即可:(只要下载前俩就行了,后边都是自动安装了)(直到这是我才发现protobuf所依赖的其他包都已经展示出来了,就是下边自动安装的那些) 客户端: Unity如何使用protobuf? 1、我以为在工程里直接下NuGet包即可,才发现Unity的C#工程里面没有NuGet。 2、我从网上搜资料,大部分人都说,把Google.Protobuf.dll移入Asset文件夹即

HP_69的博客 1254

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Unity中使用Protobuf

如何在Unity项目中使用Protobuf,本文给了全生命周期的流程性指导

weixin_39196123的博客 2950

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Unity_C#中使用protobuf

生成的文件位于 protobuf-22.2/csharp/src/Google.Protobuf/bin/Release/net45 目录下。Release 模式,然后右键选中 Google.Protobuf -> 生成,可生成需要的 dll 文件。

原在路上的博客。 1121

unity protobuf

整理Unity网络协议模块Protobuf-net生成cs 最近公司项目调整,工作不忙,抽点时间深入学习一下项目的一些基础模块,作为unity开发者,同时也需要了解网络协议模块,首先从后端到前端的过程开始了解,那么就可避免地需要用到proto格式的网络协议,花了一天半时间,从无到有了解,以及使用过程,略有心得(以后用忘了咋整),记录一下下,哈哈哈哈哈哈 protobuf介绍 **(网上文章一大抄,反正不是我写滴) protocol buffers : 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,

qq_32470423的博客 906

Unity GC优化之Protobuf

Protobuf在Unity中高频使用时,GC优化非常重要。主要手段:对象池、缓冲区复用、减少装箱、优化字符串分配、选择合适库。持续用Profiler监控,针对性优化。下面继续深入讲解Unity GC优化之Protobuf的实战细节,包括具体代码示例、不同Protobuf库的对比、以及在Unity项目中的最佳实践。修改Protobuf生成的代码,手动管理字段分配和复用。用Span<byte>等新特性,减少临时数组分配(需.NET Standard 2.1+)。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 1579

Unity使用Protobuf

unity 使用protobuf

qq_25670983的博客 1056
上一篇: Unity 导出Assetbundle的脚本
下一篇: Unity3D Assetbundle的原理
我是一纸巾
博客等级 码龄12年 14粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值