Unity基于Protobuf的序列化与反序列化

1.将protobuf-net导入unity中Plugins文件夹下

2.编写代码:

using ProtoBuf;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
/*
 * protobuf的序列化与反序列化规则:
	1. 自定义类型规则:
		(1)[ProtoContract]特性:标识类可被序列化
		(2)[ProtoMember(id)]特性:标识属性可被序列化,id为数据索引,字段名修改不影响原数据
		(3)必须包含无参构造函数
	
 		实例:
			[ProtoContract]	
 			public class FData 
			{
				[ProtoMember(1)]	
				public int ID;
				[ProtoMember(2)]
				public string Name;

				public FData() {}
				public FData(int id, string name) 
				{
					ID = id;
					Name = name;
				}
			}	
	2.使用.proto文件作为配置表数据
		(1)通过protoc工具转换为cs文件,会自动添加特性
		(2)再序列化/反序列化cs对象
	3.继承问题
 */
namespace ProtobufSerialize {

	public class ProtobufSerializer {

		/// <summary>
		/// 将消息序列化为二进制
		/// </summary>
		/// <param name="model"></param>
		/// <returns></returns>
		public static byte[] Serialize<T>(T obj) {

			try {
				//涉及格式转换,需要用到流,将二进制序列化到流中  
				using (MemoryStream ms = new MemoryStream()) {
					//使用ProtoBuf工具的序列化方法  
					Serializer.Serialize(ms, obj);
					//定义二级制数组,保存序列化后的结果  
					byte[] result = new byte[ms.Length];
					//将流的位置设为0,起始点  
					ms.Position = 0;
					//将流中的内容读取到二进制数组中  
					ms.Read(result, 0, result.Length);
					return result;
				}
			}
			catch (Exception ex) {
				throw ex;
			}
		}
		/// <summary>
		/// 反序列化消息
		/// </summary>
		/// <typeparam name="T">消息类型</typeparam>
		/// <param name="bytes">二进制消息体</param>
		/// <returns>消息体</returns>
		public static T DeSerialize<T>(byte[] bytes) {
			using (MemoryStream ms = new MemoryStream()) {
				//将消息写入流中  
				ms.Write(bytes, 0, bytes.Length);
				//将流的位置归0  
				ms.Position = 0;
				//使用工具反序列化对象  
				T result = default(T);
				result = Serializer.Deserialize<T>(ms);
				return result;
			}
		}

		public static void SaveByteFile(byte[] data, string fileName) {
			using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write)) {
				try {
					fs.Write(data, 0, data.Length);
					fs.Dispose();
					fs.Close();
				}
				catch (Exception ex) {
					throw ex;
				}
			}
		}

		public static byte[] ReadByteByFile(string fileName) {
			using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) {
				try {
					byte[] buffur = new byte[fs.Length];
					fs.Read(buffur, 0, (int)fs.Length);
					fs.Dispose();
					fs.Close();
					return buffur;
				}
				catch (Exception ex) {
					throw ex;
				}
			}
		}
	}
}

 

using ProtoBuf;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using ProtobufSerialize;
[ProtoContract]
public class FData {
	[ProtoMember(1)]
	public int ID;
	[ProtoMember(2)]
	public string Name;
	[ProtoMember(3)]
	public bool IsSer;
	public FData() { }

	public override string ToString() {
		return $"ID={ID},Name={Name},IsSer={IsSer}";
	}
}
public class Test : MonoBehaviour {
	public FData Data = new FData();
	private string m_ConfigPath;
	private void Start() {
		m_ConfigPath = Application.dataPath + "/config.byte";
	}
	private void Update() {
		if (Input.GetKeyDown(KeyCode.Alpha1)) {
			byte[] result = ProtobufSerializer.Serialize(Data);
			ProtobufSerializer.SaveByteFile(result, m_ConfigPath);
		}
		if (Input.GetKeyDown(KeyCode.Alpha2)) {
			var bytes = ProtobufSerializer.ReadByteByFile(m_ConfigPath);
			var obj = ProtobufSerializer.DeSerialize<FData>(bytes);
			Debug.Log(obj.ToString());
		}
	}

}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UIElements;

[CustomEditor(typeof(Test))]
public class FDataEditor : Editor {
	public override void OnInspectorGUI() {
		base.OnInspectorGUI();
		(target as Test).Data.ID = EditorGUILayout.IntField("ID", (target as Test).Data.ID);
		(target as Test).Data.Name = EditorGUILayout.TextField("Name", (target as Test).Data.Name);
		(target as Test).Data.IsSer = EditorGUILayout.Toggle("是否", (target as Test).Data.IsSer);
		if (GUI.changed) {
			EditorUtility.SetDirty(target);
		}
	}
}

3.将Test脚本挂在到物体上运行即可看效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity中的protobuf序列化是一种将数据结构转化为字节流的方法,以便在网络传输、存储或在不同平台之间传递数据。它基于Google的protobuf (Protocol Buffers)协议,能够高效地序列化反序列化复杂的数据结构。 在Unity中使用protobuf序列化需要进行以下几个步骤: 1. 定义消息结构:首先需要在.proto文件中定义要序列化的数据结构。这包括定义消息的字段、枚举、嵌套消息等。可以指定每个字段的类型(整数、浮点数、字符串等)和标签(用于标识字段的唯一性)等信息。 2. 编译.proto文件:使用protobuf编译器将.proto文件编译为相应语言的代码。在Unity中可以使用Protobuf-net等第三方插件来生成C#代码。 3. 序列化数据:在需要序列化数据的地方,将数据按照定义好的消息结构进行赋值,并使用protobuf提供的方法将其序列化为字节流。 4. 反序列化数据:在接收端或需要解析数据的地方,使用protobuf提供的方法将字节流反序列化为消息对象,然后可以通过读取字段的方式获取其中的数据。 使用unity protobuf序列化的好处是: 1. 空间效率高:protobuf采用二进制格式进行序列化,可以将数据压缩为较小的字节流,减少网络传输和存储的空间成本。 2. 速度快:protobuf序列化反序列化速度较快,可以更有效地处理大量的数据。 3. 跨平台兼容性好:使用protobuf序列化后的数据可以在不同平台、不同语言之间共享和传输,无需担心兼容性问题。 总之,Unity中的protobuf序列化是一种在网络传输和数据存储中高效、方便的数据序列化方法,可以帮助开发者更好地处理数据结构和跨平台数据传输的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值