文章目录

    • 前言
    • 框架获取与集成
    • 使用方法
      • 基本配置
      • 自动生成序列化方法
    • 实战示例
    • 技术原理与优势
      • 二进制序列化的优势
      • SJBinary的设计特点
    • 最佳实践建议
    • 适用场景
    • 总结

前言

在Unity开发过程中,与后台交互时经常需要处理大型数据文件。当遇到一个近2MB的本地JSON文件需要解析为对象时,使用传统的JSON解析方案(无论是Unity自带的JsonUtility还是流行的Newtonsoft Json.NET)都面临着显著的性能瓶颈。在实测中,这些方案解析时间可能长达3秒以上,即使经过优化也需要约1.5秒,同时还伴随着大量的GC(垃圾回收)开销。

针对这一问题,我们开发了一个高性能的二进制序列化框架——SJBinary。经过测试,该框架在性能表现上超越了市面上多数JSON框架和Unity自带的BinaryFormatter,接近Protobuf-net的性能水平,虽然略低于MessagePack,但其集成简单、代码量小的特点使其成为Unity项目中数据序列化的优秀选择。

实测数据显示,使用SJBinary创建10万个对象并序列化为二进制数据仅需480多毫秒,反序列化过程仅需340多毫秒,性能提升显著。
提示:二进制数据处理本质上比JSON处理更加高效,因为它避免了文本解析的复杂过程,直接使用二进制格式表示数据。

框架获取与集成

sjgenerate下载链接
1.点击上面链接即可下载
2.下载完后将SjBinary拖入项目即可
3.定义类并添加注解[SJBinary]及实现接口ISJSerializable

使用方法

基本配置


[SJBinary]
public class A : ISJSerializable
{public string name;public int age;public void Deserialize(SJBinaryReader reader){throw new System.NotImplementedException();}public void Serialize(SJBinaryWriter writer){throw new System.NotImplementedException();}
}

自动生成序列化方法

  • 点击Unity顶部菜单栏:Tools -> SJBinary -> Generate Methods
  • 系统将自动实现Deserialize和Serialize方法

生成的类结构如下:

[SJBinary]
public class B : ISJSerializable
{public string name;public int age;public void Serialize(SJBinaryWriter writer){writer.Write(this.name);writer.Write(this.age);}public void Deserialize(SJBinaryReader reader){this.name = reader.ReadString();this.age = reader.ReadInt32();}
}

实战示例

以下是一个完整的使用示例,展示了如何在Unity中使用SJBinary进行高效序列化和反序列化:

public class ErJinZhiSample : MonoBehaviour
{//优化前497 343msprivate List<byte[]> serializedData = new List<byte[]>();public List<TestA> deserializedObjects = new List<TestA>();private const int count = 100000;public Button btnLoad;public Button btnCreate;// 复用的 readerprivate SJBinaryReader reader;void Start(){btnLoad.onClick.AddListener(TestLoad);btnCreate.onClick.AddListener(TestCreate);}void TestCreate(){serializedData.Clear();var writer = new SJBinary.SJBinaryWriter(1024); // 可复用缓冲区Stopwatch sw = Stopwatch.StartNew();for (int i = 0; i < count; i++){writer.Reset(); // 复用缓冲区TestA obj = new TestA{age = i,name = $"Name_{i}",time = DateTime.Now.Ticks,actions = "Run,Jump",actionsList = new List<string> { "Run", "Jump", "Walk" },ids = new List<int> { 1, 2, 3 },pads = new List<int> { 10, 20, 30 }};obj.Serialize(writer);// 保存二进制数据(注意这里保存的是 ArraySegment 以避免复制)serializedData.Add(writer.GetBytes());}sw.Stop();UnityEngine.Debug.Log($"[Create] Created and serialized {count} objects in {sw.ElapsedMilliseconds} ms");}void TestLoad(){deserializedObjects.Clear();Stopwatch sw = Stopwatch.StartNew();for (int i = 0; i < count; i++){byte[] data = serializedData[i];// 复用 readerif (reader == null)reader = new SJBinary.SJBinaryReader(data);elsereader.SetBuffer(data, 0, data.Length);TestA obj = new TestA();obj.Deserialize(reader);deserializedObjects.Add(obj);}sw.Stop();UnityEngine.Debug.Log($"[Load] Deserialized {count} objects in {sw.ElapsedMilliseconds} ms");}
}

技术原理与优势

二进制序列化的优势

1.高效性能: 二进制格式避免了文本解析的复杂性,直接读写内存数据
2.紧凑体积: 二进制数据通常比等效的JSON文本小30%-50%
3.低GC开销: 通过缓冲区复用和零拷贝技术大幅减少垃圾回收压力

SJBinary的设计特点

1.简单集成: 只需添加注解和接口实现,无需复杂配置
2.代码生成: 提供工具自动生成序列化代码,减少手动编写错误
3.缓冲区复用: 支持读写缓冲区的复用,极大减少内存分配
4.类型安全: 编译时检查类型一致性,避免运行时错误

最佳实践建议

1.适当初始化缓冲区大小: 根据典型数据大小初始化缓冲区,避免频繁扩容
2.复用读写器实例: 特别是在循环中处理多个对象时
3.处理版本兼容性: 当数据结构变化时,需要考虑向后兼容性策略
4.异常处理: 在序列化和反序列化过程中添加适当的异常处理机制

适用场景

SJBinary特别适用于以下场景:

  • 需要频繁序列化/反序列大量数据的游戏
  • 对性能敏感的网络通信应用
  • 需要持久化大量游戏状态的单机游戏
  • 需要快速加载大型配置文件的应用程序

总结

SJBinary为Unity开发者提供了一个简单易用且高性能的二进制序列化解决方案。通过其简洁的API设计和高效的实现,它能够显著提升数据处理的性能,同时保持较低的内存开销。对于需要处理大量数据的Unity项目,SJBinary是一个值得考虑的轻量级解决方案。

如果您在使用过程中有任何建议或问题,欢迎在评论区留言反馈。我们将持续优化和改进这个框架,以满足更多开发场景的需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/919801.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/919801.shtml
英文地址,请注明出处:http://en.pswp.cn/news/919801.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

​Kubernetes 详解:云原生时代的容器编排与管理

一 Kubernetes 简介及部署方法 1.1 应用部署方式演变 在部署应用程序的方式上&#xff0c;主要经历了三个阶段&#xff1a; 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其它技术的参与 缺点&#xf…

Kotlin 中的枚举类 Enum Class

枚举类在 Kotlin 中是非常强大和灵活的工具,可以用于表示一组固定的常量,并且可以包含属性、方法、构造函数和伴生对象。它们在处理状态、选项等场景中非常有用。 1、枚举类的定义 枚举类用于创建具有一组数量有限的可能值的类型。 枚举的每个可能值都称为“枚举常量”。每个…

集成电路学习:什么是K-NN最近邻算法

K-NN:最近邻算法 K-NN,即K-最近邻算法(K-Nearest Neighbor algorithm),是一种基本的监督学习算法,广泛应用于分类和回归问题中。以下是对K-NN算法的详细解析: 一、K-NN算法的基本原理 1、K-NN算法的核心思想是: 对于一个新的数据点,算法会在训练数据集中找到与…

2025最新版mgg格式转MP3,mflac转mp3,mgg格式如何转mp3?

注&#xff1a;需要使用旧版客户端&#xff0c;并需要禁用更新。使用说明内有链接打开软件&#xff0c;可以选择将待转换的歌曲拖入&#xff1b;或者点击添加将mgg或者mflac歌曲拖入点击开始转换等待一会就转换完成&#xff0c;默认转换后的歌曲存在桌面的【转换成功】的文件夹…

嵌入式学习day34-网络-tcp/udp

day33练习&#xff1a;客户端 与 服务器实现一个点对点聊天tcp客户端clifd socketconnect//收 --父进程 //发 --子进程 tcp服务器 listenfd socketbindlistenconnfd accept()//收 -- 父进程 //发 -- 子进程client.c#include "../head.h"int res_fd[1]; // 只需要存…

零知开源——基于STM32F103RBT6与ADXL362三轴加速度计的体感迷宫游戏设计与实现

✔零知IDE 是一个真正属于国人自己的开源软件平台&#xff0c;在开发效率上超越了Arduino平台并且更加容易上手&#xff0c;大大降低了开发难度。零知开源在软件方面提供了完整的学习教程和丰富示例代码&#xff0c;让不懂程序的工程师也能非常轻而易举的搭建电路来创作产品&am…

《Linux 网络编程一:网络编程导论及UDP 服务器的创建与数据接收》

Linux下的网络编程1. 目的实现不同主机之间进程的通信。2. 问题主机之间在物理层面必须互联互通。进程之间在软件层面必须互联互通。IP地址&#xff1a;计算机的软件地址&#xff0c;用于标识计算机设备。MAC地址&#xff1a;计算机的硬件地址&#xff08;固定&#xff09;。网…

排序(数据结构)

比较排序 插入排序&#xff08;斗地主摸牌就是一个插入排序&#xff09; 单纯的插入排序也叫直接插入排序 时间复杂度&#xff1a; 最好O(n)最坏O(n^2) 过程 先写单趟&#xff0c;再写整体 依次比较&#xff0c;如果大于就往后挪动&#xff0c;否则就退出循环&#xff0c;插入数…

【C++组件】Elasticsearch 安装及使用

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;C框架/库 目录&#x1f525; 介绍 &#x1f525; ES 安装 &#x1f98b; 安装 kibana&#x1f98b; ES 客户端的安装&#x1f525; ES 核心概念 &#x1f98b; 索引&#xff08;Index&#xff09;&…

项目:电动车报警器

1.项目需求 点击遥控器A按键&#xff0c;系统进入警戒模式&#xff0c;一旦检测到震动(小偷偷车)&#xff0c;则喇叭发出声响报警&#xff0c;吓退小偷。 点击遥控器B按键&#xff0c;系统退出警戒模式&#xff0c;再怎么摇晃系统都不会报警&#xff0c;否则系统一直发出尖叫&a…

GDSFactory环境配置(PyCharm+Git+KLayout)

1、安装 PyCharm 和 KLayout 安装 PyCharm&#xff08;官网社区版即可&#xff09;和 KLayout&#xff08;官网最新版&#xff09;&#xff0c;这两款软件均开源&#xff0c;安装操作简单&#xff0c;这里不再赘述。&#xff08;注意&#xff1a;PyCharm软件是否安装成功以能否…

STM32 定时器(输出模式)

⚙️ ​一、输出模式总览​STM32定时器的输出比较模式通过比较计数器&#xff08;CNT&#xff09;与捕获/比较寄存器&#xff08;CCRx&#xff09;的值&#xff0c;控制输出引脚&#xff08;OCx&#xff09;的电平状态。六种模式定义如下&#xff1a;​模式宏​​触发动作​&am…

嵌入式硬件篇---手柄

手柄原理&#xff1a;手柄遥控的原理其实可以简单理解为 “信号的发送与接收”&#xff0c;就像两个人用对讲机聊天&#xff0c;一方说话&#xff08;发送信号&#xff09;&#xff0c;另一方听话&#xff08;接收信号&#xff09;&#xff0c;然后根据内容行动。下面用通俗的方…

数据库架构开发知识库体系

摘要面向初创与企业团队&#xff0c;系统梳理数据库与数据平台从采集、传输、存储、处理、服务化到治理与安全的全链路。覆盖 OLTP/OLAP/HTAP、湖仓一体与实时数据栈&#xff0c;结合国内外工具与方法论&#xff0c;给出架构选型、性能优化、可靠性与合规要点&#xff0c;以及可…

在Excel和WPS表格中合并多个单元格这样最快

如果要把WPS表格和Excel中多个单元格的数据合成到一个单元格中&#xff0c;不用函数&#xff0c;只需要先写输入公式&#xff0c;然后在各个单元格之间输入&符号即可。&#xff08;当然&#xff0c;&符号不只是连接单元格的数据&#xff0c;也可以直接输入内容连接&…

在嵌入式上用 C++14实现简单HSM状态机

文章目录概述为什么要迁移到 C&#xff0c;以及 C 的陷阱目标与挑战为什么不能直接使用 std::function&#xff1f;解决方案&#xff1a;POD 回调与模板 Trampoline核心设计模板 trampoline 实现两种成员函数绑定策略1. **Per-Transition Context&#xff08;每个状态转移绑定一…

【unity】Obfuz加固混淆日志还原解析方案ObfuzResolver

Github | Gitee ObfuzResolver是基于obfuz-tools针对Obfuz的一项辅助工具&#xff0c;方便开发者在unity编辑器中或者运行时快捷将使用Obfuz混淆加固后的日志信息还原为原始信息&#xff0c;以辅助开发者快速定位Bug。 特性 支持unity编辑器模式下还原被加固混淆的日志信息&a…

2025DevOps平台趋势解读:哪些DevOps工具正在引领行业变革?

DevOps平台已成为企业提升研发效能、实现敏捷交付的核心支柱。2025年DevOps领域正经历深刻变革&#xff0c;平台能力正从“工具链整合”向“价值流智能中枢”跃升。01. 2025Devops平台趋势解读“全栈式”与“模块化/可组合”的平衡&#xff1a;企业既需要能覆盖开发、测试、部署…

第二阶段Winform-4:MDI窗口,布局控件,分页

1_MDI窗口 &#xff08;1&#xff09;MDI是指将多控件窗体在同一窗体中打开,可以设置重叠打开&#xff0c;平捕打开等&#xff0c;MDI窗体&#xff08;Multiple-Document Interface&#xff0c;多文档界面&#xff09;用于同时显示多个文档。在项目中使用MDI窗体时&#xff0c…

实用R语言机器学习指南:从数据预处理到模型实战(附配套学习资源)

一、为什么需要掌握机器学习建模&#xff1f;在科研与项目实践中&#xff0c;机器学习已成为数据挖掘的核心工具。本文手把手带你在R语言中实现7大常用模型&#xff1a;逻辑回归/正则化回归决策树/随机森林SVM支持向量机XGBoost梯度提升神经网络全程包含数据标准化→模型训练→…