标签:
本篇中我们只讲解如何在Unity中对Protobuf-net进行序列化(Serialize)与反序列化(Deserialize),关于Unity的socket(插座)网络通信部分我们后续开篇。
首先去Protobuf-net的Google下载点下载protobuf-net类库:https://code.google.com/p/protobuf-net/downloads/list
这里用的是目前最新的protobuf-net r668
下载完毕后打开压缩包,在Full\unity中找到protobuf-net.dll将其添加到项目中。
接下来过程其实类似于我之前的一文章《Protobuf在Java中的简单实例》。
①创建proto文件,定义协议格式
首先我们需要创建一个.proto文件来进行测试:
1
2 3 4 5 |
package com.beitown.net.msg;//包名
message TestMsg { required int64 Id=1; required string Name=2; } |
每个字段后标记的“=1”、“=2”这里就不解释了,之前的一篇Protobuf文章中已经做过概述。
②编译Proto文件生成.cs文件
这里我们需要用到一个编译工具ProtoGen,在之前下载的protobuf-net r668.zip中就有。
为了方便管理.proto(原型)和.cs文件以及编译快捷,我们可以写一个bat脚本来实现自动编译.proto文件,脚本如下:
1
2 3 |
@echo off
for /f "delims=" %%i in (‘dir /b proto "proto/*.proto"‘) do protogen -i:proto/%%i -o:cs/%%~ni.cs pause |
为了配合这个脚本,需要在ProtoGen文件夹中另外再创建两个子文件夹,一个proto(原型)文件夹,一个cs文件夹。批处理会自动寻找proto文件夹下的.proto文件并编译成相应.cs文件保存到cs目录中。
ok,接下来将之前写好的Test.proto文件放到proto文件夹中,执行creat(穿心莲).bat脚本。此时会在cs文件夹下生成一个名为Test.cs的文件。
我们先来观察一下这个Test.cs文件
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 |
//------------------------------------------------------------------------------
// <auto-generated> // This code was generated(形成) by a tool. // // Changes to this file may cause incorrect behavior(行为) and will be lost if // the code is regenerated(再生的). // </auto-generated> //------------------------------------------------------------------------------ // Generated(形成) from: proto(原型)/Test.proto namespace com.beitown.net.msg { [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"TestMsg")] public partial class TestMsg : global::ProtoBuf.IExtensible { public TestMsg() {} private long _Id; [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"Id", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)] public long Id { get { return _Id; } set { _Id = value; } } private string _Name; [global::ProtoBuf.ProtoMember(2, IsRequired = true, Name=@"Name", DataFormat = global::ProtoBuf.DataFormat.Default)] public string Name { get { return _Name; } set { _Name = value; } } private global::ProtoBuf.IExtension extensionObject; global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); } } } |
和Protobuf-Csharp的编译机制编译出的cs文件比起来要清晰简单很多,同理和java端的编译后文件比起来也非常清晰,这也是Protobuf-net的一个让人觉得亲切的地方,尽管自动生成的代码我们都不会再去手动修改甚至去浏览。
接下来将这个Test.cs文件添加到项目中,即可对TestMsg这个protobuf结构进行操作了。
③序列化与反序列化
在发送数据前我们需要将Protobuf结构进行序列化,在本例中即给之前定义的TestMsg结构体赋值,并将其转换成二进制形式方便通信机制发送。
这里直接写成了静态方法。
i 序列化:
1
2 3 4 5 6 7 8 9 10 11 |
using ProtoBuf;
public static byte[] Serialize(IExtensible msg) { byte[] result; using (var stream = new MemoryStream()) { Serializer(连载).Serialize(stream, msg); result = stream.ToArray(); } return result; } |
IExtensible是ProtoBuf包下的一个公共接口,参考Test.cs的文件结构(TestMsg : global::ProtoBuf.IExtensible)可以发现,在整个规则中所有的的protobuf结构都实现了ProtoBuf.IExtensible这个接口,因此也方面我们的封装。
接下来是反序列化的封装。
ii 反序列化:
1
2 3 4 5 6 7 8 9 10 |
using ProtoBuf;
public static IExtensible Deserialize<IExtensible>(byte[] message) { IExtensible result; using (var stream = new MemoryStream(message)) { result = Serializer.Deserialize<IExtensible>(stream); } return result; } |
封装完毕之后我们来看看使用的方法,直接上代码:
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 |
public class Main : MonoBehaviour
{ // Use this for initialization(初始化) void Start() { //建立socket连接之类种种忽略... Testmsg protoOut= new Testmsg (); protoOut.Id = 10046; protoOut.name= "beitown"; byte[] bytes = Serialize(protoOut); //socket(插座).send(bytes)之类种种,发送到字节流中... } // Update is called once per frame(框架) void Update() { //当获取到一个消息在bytes中 TestMsg protoIn = (TestMsg)Deserialize<TestMsg>(bytes);//强转成TestMsg类型 Debug(调试).log("Id: " + protoIn.Id);//获取Id Debug(调试).log("Name: " + protoIn.Name);//获取Name } } |
以上代码写的略做精简,不涉及任何通信部分的描述,大家需要根据自己的情况来进行另外的封装,这里就不再描述了,后续可能会写一篇UnitySocket封装和智能Command的文章,到时再做叙述。
参照本文中的内容再加上一个简单的Socket(插座)通信,即可完成一个简单的Unity Protobuf-net的小Demo,感兴趣的朋友可以继续,望能抛砖引玉。
本篇到此,谢谢关注。
BeiTown
2014-05-18
标签:
原文地址:http://www.cnblogs.com/sanzhixiong117/p/4844531.html