Unity——脚本与序列化
在介绍序列化之前,我们先来了解一下为什么要对数据进行序列化
数据序列化有以下几个主要的应用场景和目的:
1. 持久化存储:序列化可以将对象或数据结构转换为字节序列,使得其可以被存储在磁盘上或数据库中。通过序列化,我们可以将应用程序中运行时的数据持久化保存,以便在后续运行时重新加载和使用。
2. 数据传输:序列化可以将对象转换为字节序列,以便在网络上进行传输。通过序列化,我们可以方便地将数据发送给远程服务器或其他系统,实现不同系统之间的数据交互和通信。
3. 数据缓存:序列化可以将对象存储在缓存中,以提高读取和访问的性能。通过序列化,我们可以将经常需要使用的数据对象序列化到缓存中,避免频繁地从数据库或其他存储介质中读取数据,从而提高应用程序的响应速度和效率。
4. 跨平台和版本兼容性:通过序列化,我们可以将对象转换为一种通用的数据格式,如 XML 或 JSON,使得数据在不同的平台和系统之间可以进行传递和解析。而且,序列化也留下了数据的结构信息,使得即使在对象结构发生变化或升级时,仍能够进行兼容性处理。
5. 调试和日志记录:在调试过程中,我们可以将对象的状态序列化为日志文件,以便后续查看和分析。通过序列化,我们可以捕获应用程序在某一特定时刻的状态,并将其存储下来,方便调试和故障排查。
总结来说,数据序列化可以使数据在不同的环境和系统中进行存储、传输和使用,以及提供持久化存储、数据交互、性能优化和兼容性处理等方面的好处。
一、序列化的概念
计算机硬盘中的文件只能保存纯数据,不能直接保存对象,网络传输亦是如此。在游戏存档、发送网络数据包的时候,都需要先将数据转化为纯粹的二进制数据,才能进行发送。反之,读取存档、接收数据包的时候,要进行相反的操作——把二进制数据转化为对象。
将对象转化为二进制数据的操作就叫做“序列化(Seriallize)”;相反的过程,将二进制数据转化为对象就叫做“反序列化(Deseriallize)”。
常用的序列化方案有以下几种:
- 自定义二进制序列化
- C#提供的序列化方案
- JSON
- XML
- 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、应用实例
这里举一个能够在游戏退出时仍然保存数值的计数器
- 在场景中创建一个3D Text
- 默认的3D Text有点模糊,建议将Font Size设置为50,然后缩小Character Size为0.2(Font Size决定字符间隔大小,Character Size决定字体大小)
- 创建脚本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/[公司名].[产品名].plist3. Linux:
在Linux系统中,PlayerPrefs数据默认保存在用户主目录的".config"目录下。具体路径为:
~/.config/unity3d/[公司名]/[产品名]/4. iOS:
在iOS设备上,PlayerPrefs数据会存储在应用的沙盒目录中。具体路径取决于应用的Bundle Identifier。5. Android:
在Android设备上,PlayerPrefs数据会存储在设备的Shared Preferences中,并根据应用的包名进行命名,并保存在应用的沙盒目录下。
需要注意的是,PlayerPrefs保存的数据是以明文形式存储的,因此不推荐将敏感或重要的数据直接保存在PlayerPrefs中。
相关文章:
Unity——脚本与序列化
在介绍序列化之前,我们先来了解一下为什么要对数据进行序列化 数据序列化有以下几个主要的应用场景和目的: 1. 持久化存储:序列化可以将对象或数据结构转换为字节序列,使得其可以被存储在磁盘上或数据库中。通过序列化ÿ…...
NJ求职盘点
电子显示 集成电路 地平线 后摩智能 芯启源 自动驾驶 地平线 栖霞区兴智科技园 泊车、SLAM/3D算法工程师 https://wecruit.hotjob.cn/SU64819a4f2f9d2433ba8b043a/pb/social.html?currentPage1 后摩智能 栖霞区兴智科技园 视觉感知算法资深工程师 可以做自动驾驶前瞻性…...
01卡特兰数
卡特兰数跟排列组合很有关系,所以在看此文章前请掌握: 加法原理乘法原理A(m,n)计算公式及其原理C(m,n)计算公式及其原理 前言 今天您将会学习到基本的卡特兰数及其应用。 一、卡特兰数是什么? 卡特兰数(Catalan number࿰…...

若依前端vue设置子路径
若依前端vue设置子路径 说明:本文档中以前后端分离版为例,版本为:3.8.6 一设置变量 在.env.development和.env.production 中定义一个变量如VUE_APP_PROJECT_IDENTIFIER # 项目标识字符 VUE_APP_PROJECT_IDENTIFIER admin二引用路径变量 ${process…...
Vue中使用pdf.js实现在线预览pdf文件流
以下是在Vue中使用pdf.js实现在线预览pdf文件流的步骤: 1. 安装pdf.js npm install pdfjs-dist2. 引入pdf.js 在需要使用的组件中,使用以下代码引入pdf.js: import pdfjsLib from pdfjs-dist3. 加载pdf文件流 使用pdf.js的getDocument()方…...

态、势、感、知与时空、关系
态势感知是一种通过收集、整合、分析和解释大量的时空数据,以获取关于特定领域、地区或事件的全面理解的过程。时空和关系在态势感知中扮演着非常重要的角色。 态:态指的是物体或系统所处的状态或状况。在不同的态下,物体或系统的性质、行为和…...

D. Paths on the Tree
Problem - 1746D - Codeforces 思路:先分析一下题意,根据第一条性质,每次只能够从1开始,而第二条性质则表明对于每个节点来说,经过这个节点的子节点的路径条数应该尽量均衡,最大值与最小值相差不能超过1&am…...

CocosCreator3.8研究笔记(九)CocosCreator 场景资源的理解
相信很多朋友都想知道, Cocos Creator 资源的定义? Cocos Creator 常见的资源包含哪些?Cocos Creator 资源的管理机制是什么样的? Cocos Creator 中所有继承自 Asset 的类型都统称资源 ,例如:Texture2D、Sp…...

大数据课程L1——网站流量项目的概述整体架构
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解网站流量项目的案例概述; ⚪ 了解网站流量项目的数据埋点和采集; ⚪ 了解网站流量项目的整体架构; 一、网站流量项目概述 1. 背景说明 网站流量统计是改进网站服务的重要手段之一…...

提升数据库安全小技巧,使用SSH配合开源DBeaver工具连接数据库
title: 提升数据库安全小技巧,使用SSH配合开源DBeaver工具连接数据库 categories: 独立博客的方方面面 前段时间, 未来降低网址运行成本,搭了一套Mysql Docker 数据库, 包括外部链接,数据备份,数据导出,数据恢复一套解…...

信息安全技术概论-李剑-持续更新
图片和细节来源于 用户 xiejava1018 一.概述 随着计算机网络技术的发展,与时代的变化,计算机病毒也经历了从早期的破坏为主到勒索钱财敲诈经济为主,破坏方式也多种多样,由早期的破坏网络到破坏硬件设备等等 ,这也…...

java项目基于 SSM+JSP 的人事管理系统
java项目基于 SSMJSP 的人事管理系统 博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 大家好,今天和大家聊的是 Java 基于 SSM 的人事管理系统。…...

【Node.js】—基本知识点总结
【Node.js】—基本知识总结 一、命令行常用操作 二、Node.js注意点 Node.js中不能使用BOM和DOM操作 总结 三、Buffer buffer是一个类似于数组的对象,用于表示固定长度的字节序列buffer的本质是一段内存空间,专门用来处理二进制数据 特点:…...

Leetcode.174 地下城游戏
题目链接 Leetcode.174 地下城游戏 hard 题目描述 恶魔们抓住了公主并将她关在了地下城 d u n g e o n dungeon dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里,他必须穿过地下城并通过对抗恶魔来拯救公…...

python实现adb辅助点击屏幕工具
#!/usr/bin/env python # -*- coding: utf-8 -*-import re import os import time import subprocess import tkinter as tk from tkinter import messagebox from PIL import Image, ImageTk# 设置ADB路径(根据你的系统和安装路径进行调整) ADB_PATH C…...

智能合约安全分析,针对 ERC777 任意调用合约 Hook 攻击
智能合约安全分析,针对 ERC777 任意调用合约 Hook 攻击 Safful发现了一个有趣的错误,有可能成为一些 DeFi 项目的攻击媒介。这个错误尤其与著名的 ERC777 代币标准有关。此外,它不仅仅是众所周知的黑客中常见的简单的重入问题。 这篇文章对 …...
nodejs 爬虫 axios 异步爬虫 教程 【一】
axios 自定义headers axios.defaults.headers.common["User-Agent"] "Googlebot/2.1 (http://www.google.com/bot.html)"; 运行环境: node :v18 const axios require("axios"); axios.defaults.headers.common["U…...
Swift学习笔记三(Dictionary 篇)
1 Dictionary 概念 字典储存无序的互相关联的同一类型的键和同一类型的值的集合。字典类型的全写方式 Dictionary<Key, Value>,简写方式 [Key: Value],建议使用简写方式。字典的 key 必须是可哈希的。 2 Dictionary创建 2.1 初始器创建方式 2.2 …...
javax.mail 遇到501 mail from address must be same as authorization user 的問題
使用不同的兩個帳戶发送email时,第一个账户可以发送成功,但到第二个账户的时候就报出了501 mail from address must be same as authorization user的错误。 具体代码如下: import java.util.Date; import java.util.List; import java.util.…...

【Python】网络编程
Socket Socket (简称 套接字)是进程之间通信一个工具,进程之间想要进行网络通信需要socket。Socket负责进程之间的网络数据传输,好比数据的搬运工。 客户端和服务端 2个进程之间通过Socket进行相互通讯,就必须有服务端和客户端 Socket服务…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...