关键词:
- Unity3D
- ProtoBuf
- 序列化
开发环境:
- 引擎版本: Unity3D 5.4.1f1 Personal
简述
前段时间在看一个unity3d教程,在教程项目中用到了ProtoBuf,然后我在编写完代码之后运行时报错了,检测若干遍代码逻辑,最后发现是忘了写[ProtoContract],所以记录一下使用方法和问题。
简单使用方法
将ProtoBuf倒入到项目中
一般来说,有两种方式可以将ProtoBuf倒入到自己的项目中:
- 从Github下载ProtoBuf的源码放入自己的工程。
- 将编译好的dll库放入自己的工程。
这里我从网上下载了一个protobuf-net.dll文件,直接放到了我的unity3d项目下。
一个使用ProtoBuf的示例
using System;
//需要用到MemoryStream
using System.IO;
using UnityEngine;
//引入ProtoBuf命名空间
using ProtoBuf;
/// <summary>
/// 测试类
/// </summary>
public class TestProtobuf : MonoBehaviour {
/// <summary>
/// 用于测试的数据类
/// </summary>
[ProtoContract] //声明这个类能被序列化
public class UserData
{
//声明每一个需要被序列化的成员,编号从1开始
[ProtoMember(1)]
public int id;
[ProtoMember(2)]
public string name;
[ProtoMember(3)]
public int level;
}
//测试代码
void Start()
{
//将要被序列化的UserData示例
UserData user1 = new UserData ();
user1.id = 1;
user1.name = "User1";
user1.level = 10;
//打印user1
Debug.Log (string.Format ("user1-> id:{0}, name:{1}, level:{2}", user1.id, user1.name, user1.level));
//序列化
byte[] buff = null;
using (MemoryStream ms = new MemoryStream ()) {
Serializer.Serialize<UserData> (ms, user1);
ms.Position = 0;
int length = (int)ms.Length;
buff = new byte[length];
ms.Read (buff, 0, length);
}
//输出字节数组
Debug.Log (string.Format("Serialized data-> {0}", BitConverter.ToString(buff)));
//反序列化
UserData user2 = default(UserData);
using (MemoryStream ms = new MemoryStream (buff)) {
user2 = Serializer.Deserialize<UserData> (ms);
}
//打印反序列化生成的user2
Debug.Log (string.Format ("user2-> id:{0}, name:{1}, level:{2}", user2.id, user2.name, user2.level));
}
}
使用ProtoBuf对一个数据类进行序列化和反序列化的过程如上代码。
我将这段代码保存为TestProtobuf.cs文件,并添加到我的Camera对象上,运行结果如图:
总结
对于ProtoBuf的用途已经有太多博客去进行描述,对于ProtoBuf我目前也没有特别的使用技巧,在此就不赘述了。
以下补充以下需要注意的问题:
- 对需要序列化的类,两种声明([ProtoContract],[ProtoMember(编号)])一定要记得添加。如果未对类添加[ProtoContract]声明,在进行序列化时会报错,提示找不到对应的类。如果未对成员添加[ProtoMember(编号)]声明,则该成员不会被序列化,其他成员不受影响。如果[ProtoMember(编号)]声明的编号使用了0,运行时会报错参数超出范围,如果在一个类中使用了重复的编号,运行时会报错提示参数重复。
- 在实际项目中使用ProtoBuf时,尽量将序列化和反序列化的逻辑使用泛型封装起来。