Unity——脚本序列化

在介绍序列化之前,我们先来了解一下为什么要对数据进行序列化

数据序列化有以下几个主要的应用场景和目的:

1. 持久化存储:序列化可以将对象或数据结构转换为字节序列,使得其可以被存储在磁盘上或数据库中。通过序列化,我们可以将应用程序中运行时的数据持久化保存,以便在后续运行时重新加载和使用。

2. 数据传输:序列化可以将对象转换为字节序列,以便在网络上进行传输。通过序列化,我们可以方便地将数据发送给远程服务器或其他系统,实现不同系统之间的数据交互和通信。

3. 数据缓存:序列化可以将对象存储在缓存中,以提高读取和访问的性能。通过序列化,我们可以将经常需要使用的数据对象序列化到缓存中,避免频繁地从数据库或其他存储介质中读取数据,从而提高应用程序的响应速度和效率。

4. 跨平台和版本兼容性:通过序列化,我们可以将对象转换为一种通用的数据格式,如 XML 或 JSON,使得数据在不同的平台和系统之间可以进行传递和解析。而且,序列化也留下了数据的结构信息,使得即使在对象结构发生变化或升级时,仍能够进行兼容性处理。

5. 调试和日志记录:在调试过程中,我们可以将对象的状态序列化为日志文件,以便后续查看和分析。通过序列化,我们可以捕获应用程序在某一特定时刻的状态,并将其存储下来,方便调试和故障排查。

总结来说,数据序列化可以使数据在不同的环境和系统中进行存储、传输和使用,以及提供持久化存储、数据交互、性能优化和兼容性处理等方面的好处。


一、序列化的概念

计算机硬盘中的文件只能保存纯数据,不能直接保存对象,网络传输亦是如此。在游戏存档、发送网络数据包的时候,都需要先将数据转化为纯粹的二进制数据,才能进行发送。反之,读取存档、接收数据包的时候,要进行相反的操作——把二进制数据转化为对象。

将对象转化为二进制数据的操作就叫做“序列化(Seriallize)”;相反的过程,将二进制数据转化为对象就叫做“反序列化(Deseriallize)”。

常用的序列化方案有以下几种:

  1. 自定义二进制序列化
  2. C#提供的序列化方案
  3. JSON
  4. XML
  5. ProtoBuf

1、自定义二进制序列化

自定义二进制序列化是一种在代码级别定义对象如何转换为二进制数据的过程,以及如何将二进制数据转换回对象。在Unity中,通过自定义二进制序列化,我们可以完全控制对象的序列化和反序列化过程,以适应特定的需求。

下面是一个简单的示例,演示如何自定义二进制序列化:


首先,我们需要为要序列化的对象创建一个自定义的数据结构。

[Serializable]
public class CustomData
{public int value1;public float value2;// ...
}

 然后,我们可以创建一个自定义的二进制序列化器。

public static class CustomSerializer
{public static byte[] Serialize(CustomData data){MemoryStream stream = new MemoryStream();BinaryWriter writer = new BinaryWriter(stream);// 将字段写入二进制流中writer.Write(data.value1);writer.Write(data.value2);// ...writer.Close();return stream.ToArray();}public static CustomData Deserialize(byte[] data){MemoryStream stream = new MemoryStream(data);BinaryReader reader = new BinaryReader(stream);CustomData customData = new CustomData();// 从二进制流中读取字段customData.value1 = reader.ReadInt32();customData.value2 = reader.ReadSingle();// ...reader.Close();return customData;}
}

最后,我们可以使用自定义的二进制序列化器来序列化和反序列化对象。

CustomData obj = new CustomData();
// 设置对象的值...byte[] serializedData = CustomSerializer.Serialize(obj);// 将二进制数据存储到磁盘或发送给其他系统...CustomData deserializedObj = CustomSerializer.Deserialize(serializedData);// 使用反序列化后的对象...

通过自定义二进制序列化,我们可以按需存储和传输对象的状态,或者与其他系统进行数据交换。在实际应用中,我们可能需要考虑字节顺序、对象版本控制、数据压缩等因素,以提高自定义二进制序列化的效率和可靠性。

2、C#提供的序列化方案

C# 提供了几种常用的序列化方案,用于将对象转换为字节序列并进行存储、传输或持久化。下面是一些常见的 C# 序列化方案:

1. 二进制序列化(Binary Serialization):
   C# 提供了 BinaryFormatter 类,可用于将对象序列化为二进制格式,并将其保存到文件或传输到其他地方。二进制序列化是一种简单而高效的方式,适用于需要快速序列化和反序列化的场景。但它的二进制数据不可读,也难以进行跨平台和版本兼容。

2. XML 序列化(XML Serialization):
   XML 序列化使用 `XmlSerializer` 类,将对象序列化成 XML 格式。XML 是一种自描述的格式,可读性较好,并具备跨平台和版本兼容性。通过 XML 序列化,我们可以将对象保存为 XML 文件,或将 XML 数据传输给其他系统。但 XML 格式会带来一定的性能开销,并且对于大型对象或复杂的数据结构,XML 格式可能会产生较大的文件大小。

3. JSON 序列化(JSON Serialization):
   C# 中的 JSON 序列化通过 `JsonSerializer` 类来实现。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它具有可读性好、跨平台和版本兼容性,并且与 Web 开发密切相关。JSON 序列化可以将对象转换为 JSON 格式进行存储、传输和与其他系统进行数据交互。相对于 XML 格式,JSON 格式更加紧凑,但仍然具备很好的可读性。

4. Protobuf 序列化(Protocol Buffers Serialization):
   Protobuf 是 Google 发布的一种高效的二进制序列化格式,适用于跨平台和高性能的数据传输。在 C# 中,可以使用谷歌开源的 protobuf-net库进行 Protobuf 序列化。Protobuf 的优点包括高性能、小尺寸和协议版本兼容性,但其二进制数据不可读,需要定义数据的结构和消息格式。

这些序列化方案根据不同的需求和场景可以选择合适的方案。一般而言,二进制序列化适用于性能要求较高且不需进行数据查看的场景,XML 和 JSON 序列化适用于可读性好、跨平台和版本兼容性要求较高的场景,Protobuf 序列化适用于高性能和小尺寸的数据传输。

序列化的方案还有很多,也可以自己定义独特的序列化方案。理论上来说,只要能保存并正确读取数据的序列化方案都是合理的

二、简单存储PlayerPrefs

除了通用的序列化方法外,在很多游戏和应用程序中还需要保存一些简单的游戏偏好数据(Preference)。如音乐音量、音效音量、屏幕分辨率等,某些小游戏的最高分、游戏进度也可以用简单的方式保存在设备上。

Unity提供了PlayerPrefs,以满足保存简单数据的需求。它的共嗯比较单纯,用一个键(字符串类型)对应一个之,值的类型只支持整数、浮点数和字符串3种。PlayerPrefs不擅长保存复杂数据类型,其常用方法如下

当使用Unity进行游戏开发时,可以使用PlayerPrefs类来保存和访问玩家的偏好设置和游戏数据。

1、以下是一些PlayerPrefs的常用方法示例:

1. 设置偏好设置或游戏数据:

 PlayerPrefs.SetInt("HighScore", 100); // 设置整数值PlayerPrefs.SetFloat("Volume", 0.8f); // 设置浮点数值PlayerPrefs.SetString("PlayerName", "John"); // 设置字符串值

2. 获取偏好设置或游戏数据:

   int highScore = PlayerPrefs.GetInt("HighScore"); // 获取整数值float volume = PlayerPrefs.GetFloat("Volume"); // 获取浮点数值string playerName = PlayerPrefs.GetString("PlayerName"); // 获取字符串值

3. 检查是否存在特定键:

bool hasHighScore = PlayerPrefs.HasKey("HighScore"); // 检查是否存在HighScore键

4. 删除特定键的偏好设置或游戏数据:

 PlayerPrefs.DeleteKey("HighScore"); // 删除HighScore键的数据

5. 删除所有偏好设置或游戏数据:

PlayerPrefs.DeleteAll(); // 删除所有偏好设置和游戏数据

请注意,PlayerPrefs类用于存储简单的键值对数据,不适合存储大量复杂的游戏数据。对于大型游戏或复杂数据结构,应该考虑使用其他方法,如数据序列化和数据库。

2、应用实例

这里举一个能够在游戏退出时仍然保存数值的计数器

  1. 在场景中创建一个3D Text
  2. 默认的3D Text有点模糊,建议将Font Size设置为50,然后缩小Character Size为0.2(Font Size决定字符间隔大小,Character Size决定字体大小)
  3. 创建脚本TsetPrefs经挂到3D Text上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;//这个写法的用途是强制物体具有TextMesh组件
[RequireComponent(typeof(TextMesh))]
public class TestPrefs : MonoBehaviour
{int counter = 0;TextMesh textMesh;void Start(){counter = PlayerPrefs.GetInt("counter");textMesh = GetComponent<TextMesh>();textMesh.text=counter.ToString();}// Update is called once per framevoid Update(){if(Input.GetButtonDown("Jump"))   //按空格加一{counter++;PlayerPrefs.SetInt("counter", counter);textMesh.text=counter.ToString();}if (Input.GetButtonDown("Cancel"))     //按Esc清零{counter=0;PlayerPrefs.SetInt("counter", counter);textMesh.text = counter.ToString();}}
}

完成之后就可以测试计数器效果了。运行游戏,按康哥可以让数字加1,按Esc数字清0.停止游戏后再次启动,数字会还原成上次退出时的值。

3、PlayerPrefs的实际保存位置

在Unity中,PlayerPrefs的实际保存位置取决于不同的操作系统。以下是不同操作系统上PlayerPrefs的实际保存位置:

1. Windows:
   PlayerPrefs数据在Windows系统中默认保存在注册表文件中。具体路径为:
   HKEY_CURRENT_USER\Software\[公司名]\[产品名]

2. macOS:
   PlayerPrefs数据在macOS系统中默认保存在plist文件中。具体路径为:
   ~/Library/Preferences/[公司名].[产品名].plist

3. Linux:
   在Linux系统中,PlayerPrefs数据默认保存在用户主目录的".config"目录下。具体路径为:
   ~/.config/unity3d/[公司名]/[产品名]/

4. iOS:
   在iOS设备上,PlayerPrefs数据会存储在应用的沙盒目录中。具体路径取决于应用的Bundle Identifier。

5. Android:
   在Android设备上,PlayerPrefs数据会存储在设备的Shared Preferences中,并根据应用的包名进行命名,并保存在应用的沙盒目录下。

需要注意的是,PlayerPrefs保存的数据是以明文形式存储的,因此不推荐将敏感或重要的数据直接保存在PlayerPrefs中。

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

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

相关文章

Android 13 - Media框架(9)- NuPlayer::Decoder

这一节我们将了解 NuPlayer::Decoder&#xff0c;学习如何将 MediaCodec wrap 成一个强大的 Decoder。这一节会提前讲到 MediaCodec 相关的内容&#xff0c;如果看不大懂可以先跳过此篇。原先觉得 Decoder 部分简单&#xff0c;越读越发现自己的无知&#xff0c;Android 源码真…

SQL sever命名规范

目录 一、标识符 二、表名&#xff08;Table&#xff09;: 三、字段名&#xff08;fields&#xff09;&#xff1a; 四、约束&#xff08;Constraint&#xff09;&#xff1a; 五、索引&#xff08;Index&#xff09;&#xff1a; 六、存储过程&#xff08;Stored Proced…

安卓 tcp 客户端

安卓 tcp 客户端 Server:8888 是Qt 写的Tcp 服务器 ip 是 192.168.2.103 port是8888 安卓手机运行 kotlin 语法的Tcp Client &#xff0c;连接&#xff0c;收发数据 效果如下图 Tcpclient package com.example.myapplicationimport android.os.Handler import android.os.Loo…

Debezium系列之:Debezium Server在生产环境大规模应用详细的技术方案

Debezium系列之:Debezium Server在生产环境大规模应用详细的技术方案 一、需求背景二、Debezium Server实现技术三、技术方案流程四、生成接入配置五、新增数据库接入和删除数据库接入效果六、监控zookeeper节点程序七、新增数据库接入部署debezium server程序八、删除数据库接…

Go操作各大消息队列教程(RabbitMQ、Kafka)

Go操作各大消息队列教程 1 RabbitMQ 1.1 概念 ①基本名词 当前市面上mq的产品很多&#xff0c;比如RabbitMQ、Kafka、ActiveMQ、ZeroMQ和阿里巴巴捐献给Apache的RocketMQ。甚至连redis这种NoSQL都支持MQ的功能。 Broker&#xff1a;表示消息队列服务实体Virtual Host&#x…

Java中的InetAddress类

InetAddress类 概念&#xff1a;InetAddress类是 Java 中用于表示 IP 地址的类。它提供了一种标准的方法来处理 IP 地址&#xff0c;无论是 IPv4 还是 IPv6 地址。InetAddress 类位于 java.net 包中&#xff0c;是 Java 网络编程的一部分。 常用方法&#xff1a; getLocalHost…

深入探讨梯度下降:优化机器学习的关键步骤(一)

文章目录 &#x1f340;引言&#x1f340;什么是梯度下降&#xff1f;&#x1f340;损失函数&#x1f340;梯度(gradient)&#x1f340;梯度下降的工作原理&#x1f340;梯度下降的变种&#x1f340;随机梯度下降&#xff08;SGD&#xff09;&#x1f340;批量梯度下降&#xf…

HTML5+CSS3+JS小实例:科技感满满的鼠标移动推开粒子特效

实例:科技感满满的鼠标移动推开粒子特效 技术栈:HTML+CSS+JS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport&qu…

回归拟合 | 灰狼算法优化核极限学习机(GWO-KELM)MATLAB实现

这周有粉丝私信想让我出一期GWO-KELM的文章&#xff0c;因此乘着今天休息就更新了(希望不算晚) 作者在前面的文章中介绍了ELM和KELM的原理及其实现&#xff0c;ELM具有训练速度快、复杂度低、克服了传统梯度算法的局部极小、过拟合和学习率的选择不合适等优点&#xff0c;而KEL…

HFSS 3维曲线导入

HFSS 3维曲线导入 简介环境参考代码使用结果 简介 如图一所示&#xff0c;CST中可以通过导入和到出由任意点组成的曲线&#xff0c;但是HFSS中貌似不能导入&#xff08;如图二所示&#xff09;&#xff0c;如果我们要将matlab的产生的曲线的点的数据导入特变麻烦&#xff0c;特…

测试验证平台

测试验证平台 1.功能说明&#xff1a; 模拟智能终端车端数据采集及上报的功能&#xff0c;提供数据管理平台的模拟和验证功能。 2.系统组成&#xff1a; 系统示意图 功能要求&#xff1a; 本地电脑实现Imx6配置功能&#xff0c;能够通过运行不同的脚本&#xff0c;模拟不…

大规模网络爬虫系统架构设计 - 云计算和Docker部署

在大规模网络爬虫系统中&#xff0c;合理的架构设计和高效的部署方式是确保系统稳定性和可扩展性的关键。本文将介绍如何利用云计算和Docker技术进行大规模网络爬虫系统的架构设计和部署&#xff0c;帮助你构建高效、可靠的爬虫系统。 1、架构设计原则 在设计大规模网络爬虫系…

英码科技受邀亮相2023WAIE物联网与人工智能展,荣获行业优秀创新力产品奖!

8月28日-30日&#xff0c;2023WAIE 物联网与人工智能展在深圳福田会展中心顺利举办。英码科技受邀亮相本届展会&#xff0c;并现场重点展出了面向智慧交通、智慧校园、智慧应急、智慧园区等不同行业的创新AIoT产品、AI技术服务等内容&#xff0c;与生态伙伴积极探讨市场需求和问…

CentOS配置Java环境报错-bash: /usr/local/jdk1.8.0_381/bin/java: 无法执行二进制文件

CentOS配置Java环境后执行java -version时报错&#xff1a; -bash: /usr/local/jdk1.8.0_381/bin/java: 无法执行二进制文件原因是所使用的jdk的版本和Linux内核架构匹配不上 使用以下命令查看Linux架构&#xff1a; [rootlocalhost ~]# cat /proc/version Linux version 3.1…

vue3中右侧26个英文字母排列,点击字母,平滑到响应内容

效果图如下&#xff1a; 右侧悬浮 <!-- 右侧悬浮组件 --><div class"right-sort"><div v-for"(item, index) in list" :key"index" class"sort-item" :class"index activeIndex ? sort-item-active : " c…

yolov8-ros目标检测---硬件与仿真环境中区别

为了完成使用realsenseD435i相机在真实环境下的目标检测任务&#xff0c;下载了realsense-ros和yolo8-ros功能包&#xff08;都在工作空间src下&#xff09;。分两种情况&#xff0c;1、使用真实硬件&#xff08;如realsenseD435i&#xff09;。2、在纯仿真环境下进行目标识别&…

Spring IOC的理解

总&#xff1a; 控制反转&#xff08;IOC&#xff09;&#xff1a;理论思想&#xff0c;传统java开发模式&#xff0c;对象是由使用者来进行管理&#xff0c;有了spring后&#xff0c;可以交给spring来帮我们进行管理。依赖注入&#xff08;DI&#xff09;&#xff1a;把对应的…

音频——I2S DSP 模式(五)

I2S 基本概念飞利浦(I2S)标准模式左(MSB)对齐标准模式右(LSB)对齐标准模式DSP 模式TDM 模式 文章目录 DSP formatDSP A时序图逻辑分析仪抓包 DSP B时序图逻辑分析仪抓包 DSP format DSP/PCMmode 分为 Mode-A 和 Mode-B 共 2 种模式。不同芯⽚有的称为 PCM mode 有的称为 DSP m…

20230830工作心得:巧用标记位和For循环遍历

1 巧用标记位和For循环遍历 您可以使用一个 Map<String, List<xxx>> 类型的数据结构来根据手机号分组并保存多条线索。然后&#xff0c;可以按照以下方式进行操作&#xff1a; 1. 设置一个标志位&#xff0c;比如一个布尔变量&#xff0c;用于记录是否已经成功推…

【Rust】001-基础语法:变量声明及数据类型

【Rust】001-基础语法&#xff1a;变量声明及数据类型 文章目录 【Rust】001-基础语法&#xff1a;变量声明及数据类型一、概述1、学习起源2、依托课程 二、入门程序1、Hello World2、交互程序代码演示执行结果 3、继续上难度&#xff1a;访问链接并打印响应依赖代码执行命令 三…