机械拆装-基于Unity-本地数据持久化
目录
1. 数据结构简介:数据的集合
1.1 线性数据结构
1.2 非线性数据结构
2. 对数据集合的操作:
3. 数据持久化
3.1 数据的序列化存储
3.2 JSON文件硬盘存储
3.2.1 Json文件允许存储的数据类型
3.2.2 Json文件的语法格式
3.2.3 Json文件的读取
3.2.4 Json文件的反序列化
3.2.5 Json文件的序列化写入
在场景运行过程中,会产生大量的数据,有些数据在场景切换或者游戏重启时需要一直保持,不能被销毁或者初始化,因此需要将数据保存在本地或服务器的硬盘中。比如游戏场景中,人物获取的财富、背包等数据;比如在拆装场景中,装配零件的编号、名称、3D模型等信息。
我们在存储数据的过程中,需要一定的结构或格式,以方便对数据进行遍历和编辑。大部分程序语言定义的数据结构都有具体的类型定义,不过这里不展开分析数据结构,仅举例在实际项目中对数据进行持久化管理的方法和代码。
1. 数据结构简介:数据的集合
数据结构基本分为两大类——线性、非线性数据结构
1.1 线性数据结构
主要有:数组(一维、多维)、线性表(顺序表、链表)、栈、队列、串、数组、文件。
以线性表为例,其逻辑结构是n个数据元素的有限序列,所有数据元素曾线性关系,有唯一的“第一个”和“最后一个”数据元素,并且除“第一个”和“最后一个”数据元素外,每个元素有且只有一个前驱元素和一个后继元素。我们常用的List列表就是典型的线性表。

1.2 非线性数据结构
主要有:散列表(哈希表)、树、图。
以哈希表为例,其存储数据的基本思想就是以结点的关键字为自变量,通过一定的函数关系(散列函数)计算出对应的函数值,以这个值作为该节点存储在散列表中的地址。哈希表使用节点关键字对应存储地址,查询效率高,并且可以由自己设定的函数关系来指定内存的存放规律。
2. 对数据集合的操作:
不管是哪种数据类型,对于数据的操作需要基本有编辑(增、减、修改)、排序、统计、遍历等,操作算法比较著名的有冒泡、二分法、希尔、递归等。
落地到unity的实际项目中,可以使用不同函数对不同类型的数据操作。比如最常见的列表List<T>,字典Dictionary<T, T>,常见的操作有读取数据、排序、新增数据、修改数据等,可以参考Unity开发之C#基础-列表(List)_unity list-CSDN博客 描述了对于List列表的常用操作。
3. 数据持久化
以上介绍了数据的几种方式,那么如何将这些数据保存下来,而不随着场景切换和游戏的重启而消亡。目前常用的数据存储方式有:数据序列化存储内存存储、XML文件存储、JSON文件存储、数据库存储等多种形式。以下举例两种轻量化数据持久化方式:数据序列化存储、Json文本文件硬盘存储。
3.1 数据的序列化存储
使用System.Serializable属性序列化某个类的实例,让它可以被保存并能够在Inspector窗口中可视化和编辑,方便配置其属性,如图1所示(仅为示例,实际使用时请用英文字符作为变量名)。当数据或数据类型较多时,还可以嵌套使用,例如编写一个数据管理类来管理所有的数据实例,如图2所示。

实现方法:
(1)建立需要被保存的数据类,如果此数据项目较多,还可以使用CreateAssetMenu属性将这些数据列表放到菜单中,以方便反复建立。
例如装配零件的功能,包括主轴、副轴、换挡拨叉、活塞曲柄等子装配体以及总体装配等多个装配模块,都需要记录零件的信息,那么就可以将零件信息作为一个数据类,然后建立列表管理零件信息,最后将列表建立在菜单中。代码如下:
using System;//需要调用
using System.Collections;
using System.Collections.Generic;
using UnityEngine;[Serializable]
//文件序列化
public class PartData
{//零件的信息类public int PartNo;public int AsblOrder;public String PartName;public GameObject PartObject;
}
[CreateAssetMenu(fileName = "PartData", menuName = "TangXiaoMo/PartData", order = 1)]
//将零件列表的创建放到菜单中,方便随时创建
public class PartDataConfig : ScriptableObject
{//零件的列表,记录所有零件的信息public int SceneNo;public List<PartData> PartList;
}
(2)建立零件列表List<PartData>
保存上面的代码后,我们在Assets随意位置都能创建零件的信息列表,如图所示:


在这个零件列表文件中,可以在它的Inspector中配置我们所需要的零件信息。

(3)数据修改及取用
简单的方法,先定义一个公共的PartDataConfig变量,以便于在面板中拖入相应的数据文件:
public PartDataConfig _config;

数据调用的方法如下,新建一个TestItem.cs文档:
public class TestItem : MonoBehaviour
{public PartDataConfig _config;private PartData _partData;void Start(){for (int i = 0; i < _config.PartList.Count; i++){//查询所有的零件名_partData = _config.PartList[i];Debug.Log(_config.PartList[i].PartName);}}
}
运行结果:

数据修改的方法——对于列表中的数据直接赋值,代码举例如下:按K键修改主轴的装配顺序:
void Update(){//修改数据if (Input.GetKeyDown(KeyCode.K))_config.PartList[0].AsblOrder = 10;//将装配顺序修改为10}

3.2 JSON文件硬盘存储
*.json文件是一种轻量级的数据交换格式,可以在多种编程语言中解析和使用,具有很强的可操作性。
3.2.1 Json文件允许存储的数据类型
数字型:short,int,long,float,double
字符串:"abc"、"你好"、'abc'
布尔:true false
空类型:null
数组、列表:[1,2,3]
键值对:{"key1":{"id":01}}
3.2.2 Json文件的语法格式
json文件以“键-值”对的形式存储,“键”和“值”之间使用冒号分隔;
“键-值”对之间使用逗号分隔(最后一个“键-值”对后面不能写逗号);
大括号{ }用于保存一个数据对象,支持大括号{ }嵌套;
例如:
{"PartNo": 0,"AsblOrder": 0,"PartName": "01_主轴","PartPath": "PartPrefabs/01_主轴"
}
如果要存储多个数据,例如前文中存储的多个零件信息的列表,也可以在Json文件中存为数组形式,用方括号[ ]包含,作为一个“值”,如:
{"partListID": 0,"partListName": "主轴零件","PartList": [{"PartNo": 0,"AsblOrder": 0,"PartName": "主轴","PartPath": "PartPrefabs/00_主轴"},{"PartNo": 1,"AsblOrder": 1,"PartName": "左1轴承","PartPath": "PartPrefabs/01_左1轴承"}]
}
可以将上面的文字写在记事本中,后缀名保存为*.json,并且需保存为UFT-8格式编码

3.2.3 Json文件的读取
使用File.ReadAllText读取硬盘上的Json文件。将上面保存的Json文件命名为PartDataList.json,保存在Assets/StreamingAssets文件夹下,读取代码如下:
// Json数据的读取void Start(){string str = System.IO.File.ReadAllText(Application.streamingAssetsPath + "/PartDataList.json");Debug.Log(str);}
这里使用数据流函数Application设置硬盘读取路径,有以下几种类型的路径(windows系统、IOS和安卓系统的文件夹路径各不相同):
1. Application.dataPath 存储在Assets文件夹下(相对路径)
2. Application.streamingAssetsPath 存储在Assets/StreamingAssets下(相对路径)
3. Application.persistentDataPath 存储在C盘本地持久化存储路径(可读可写)
4. Application.temporaryCachePath 存储在C盘临时路径temp
在本例中使用Application.streamingAssetsPath为读取路径,因此将PartDataList.json文件存储在Assets/StreamingAssets文件夹下。这时读取的数据没有被序列化,因此就是json源文件:

3.2.4 Json文件的反序列化
使用JsonUtility解析方法,可以将Json文件的数据进行“内存->硬盘”和“硬盘->内存”的序列化和反序列化,这样可以将上面读取的混乱的信息存入相应的数据类型中。

例如上面的零件信息Json文件——PartDataList.json,如果要将它从硬盘读取到内存,需要先建立对应的数据类,以便于将数据按类型存储到内存中,代码如下:
[Serializable]
public class PartInfo
{//零件信息数据public int PartNo;public int AsblOrder;public string PartName;public string PartPath;
}public class PartDataList
{//Json数据类public int partListID;public string partListName;public List<PartInfo> PartList;
}
随后使用JsonUtility.FromJson<>将读取的字符串数据反序列化,并存入相应的数据类型中,代码如下:
public class TestGetJson : MonoBehaviour
{// 从Json文件中获取数据,并反序列化void Start(){string str;str = System.IO.File.ReadAllText(Application.streamingAssetsPath + "/PartDataList.json");PartDataList jsonData = JsonUtility.FromJson<PartDataList>(str);}
}
在代码中打断点查看内存数据存储情况,从运行结果中可以看到,已将相应的int、string和List类型存入相应内存区域中:

3.2.5 Json文件的序列化写入
可以使用JsonUtility方法在硬盘上新建一个Json文件,并存储上述的零件信息。代码如下:
//1. 先定义和序列化需要存储的数据类型
[Serializable] //数据内容必须经过序列化才能使用JsonUtility.ToJson,否则不能完全显示
public class TestData
{//按照Json中的数据格式定义的数据类public int PartNo; //零件号public int AsblOrder; //装配顺序public string PartName; //零件名称public string PartPath; //零件模型的存放地址
}//2. 定义一个数据类,用于存放Json数据
public class TestJsonData
{public string name; public List<TestData> dataList;public TestData data;}
//3. 使用JsonUtility写入Json文件
public class TestWriteJson : MonoBehaviour
{void Start(){string str;var testJson = new TestJsonData(); //新建一个数据对象testJson.name = "主轴零件列表"; //并初始化所有变量testJson.data = null;testJson.dataList = new List<TestData>(){new TestData(){PartNo = 0,AsblOrder = 1,PartName = "主轴",PartPath = "PartPrefabs/00_主轴"}};//使用JsonUtility.ToJson序列化以上对象,并返回一个字符串str = JsonUtility.ToJson(testJson);//文件写入一个新的Json文件-writeToJson.jsonFile.WriteAllText(Application.streamingAssetsPath+"/writeToJson.json",str);}}
运行结果是在Assets/StreamingAssets文件夹下新建了一个writeToJson.json文件,文件内容如下。可以看到,虽然在初始化时,data变量赋值为null,但在实际运行时还是默认被赋了初值。
{"name":"主轴零件列表","dataList":[{"PartNo":0,"AsblOrder":1,"PartName":"主轴","PartPath":"PartPrefabs/00_主轴"}],"data":{"PartNo":0,"AsblOrder":0,"PartName":"","PartPath":""},"_private":1,"_protected":2}相关文章:
机械拆装-基于Unity-本地数据持久化
目录 1. 数据结构简介:数据的集合 1.1 线性数据结构 1.2 非线性数据结构 2. 对数据集合的操作: 3. 数据持久化 3.1 数据的序列化存储 3.2 JSON文件硬盘存储 3.2.1 Json文件允许存储的数据类型 3.2.2 Json文件的语法格式 3.2.3 Json文件的读取 3.2.4 …...
【SpringBoot】4.3.5 参数传递之ModelAndView对象
ModelAndView也是SpringMVC中常用的数据返回对象。当控制器处理完请求时,通常会将包含视图对象和数据的ModelAndView对象一起返回前台。它的作用类似request对象的setAttribute()方法。 ModelAndView对象有两个作用: 1)设置转向地址(这也是ModelAndView和ModelMap的…...
《技术人求职之道》之简历优化篇(上):量身打造简历,如何与自身情况完美匹配
摘要 在求职过程中,简历优化是提升面试机会的关键步骤。本文将探讨如何通过精心设计简历来提高求职成功率。文章将首先指出,不存在完美简历,重要的是根据个人实际情况定制简历。接着,详细介绍撰写简历时应遵循的基本原则和要素&a…...
mysql+php+html实现学生管理系统
mysqlphphtml实现学生管理系统 前言 本文使用Mysqlphphtml实现一个简单的学生管理系统,实现了登陆,注册,总览学生信息,添加学生,查询特定的学生,删除指定的学生等功能。并且本文仅用来学习就够了…...
find+rm一行命令删除文件夹及子文件夹下文件,不删除子文件夹,或者用python实现
如果你正在使用类Unix操作系统(如Linux或macOS),并希望使用命令行工具rm来删除一个文件夹及其子文件夹下的所有文件,同时保留文件夹结构,你可以使用find命令配合rm来实现这一操作。这种方法非常高效且常用于批量删除文…...
超详细的linux-conda环境安装教程
安装和配置Linux系统中的Conda环境是一个强大的工具,它可以帮助用户管理Python及其库。以下是一份超详细的Linux-Conda环境安装教程: 1. 安装前的准备 确保你的Linux系统已经更新到最新版本,并安装了基本的开发工具和库。 sudo apt-get up…...
vite项目构建配置
1、用vite搭建项目 使用npm create vitelatest构建项目,配置项选项react->tsSWC即可。 让后打开项目npm i。 2、项目配置 2.1、vite配置 主要是配置用到的插件(plugins--比如:svg、mock等)、路径、环境变量的使用、打包、…...
Java 反射机制与Spring框架的那点事
Java 反射机制是 Java 语言提供的一种能力,允许程序在运行时查询、访问和修改它自己的结构和行为。反射机制非常有用,但同时也需要谨慎使用,因为它可能会带来性能开销和安全风险。 以下是 Java 反射机制的一些关键概念和用法: Cl…...
计算机网络面试题3
四次挥手 断开连接需要四次挥手 1.客户端发送一个FIN(SEQx)标志的数据包到服务端,用来关闭客户端到服务端的数据传送, 然后客户端进入FIN-WAIT-1状态。 2.服务端收到一个FIN(SEQx)标志的数据包,它…...
day54|110.字符串接龙, 105.有向图的完全可达性, 106.岛屿的周长
110.字符串接龙 110. 字符串接龙 (kamacoder.com) #include<iostream> #include<vector> #include<unordered_set> #include<unordered_map> #include<string> #include<queue>using namespace std;int main(){int n 0;cin >> n;…...
使用docker在CentOS 7上安装php+mysql+nginx环境教程并运行WordPress
文章目录 一、安装docker1、切换yum源并更新系统2、卸载旧版docker3、配置Docker的yum库4、安装Docker5、启动和校验Docker6、配置镜像加速6.1、注册阿里云账号6.2、开通镜像服务6.3、配置镜像加速二、部署php+mysql+nginx环境1、准备目录结构2、拉取镜像3、运行容器并从中拷贝…...
vite tsx项目的element plus集成 - 按需引入踩坑
前面我们进行了开源组件的自研,很多组件可直接用现成的开源组件库,并不需要自己重复造轮子,为此我们讲如何在当前vite vitepress tsx技术整合的项目中实现element plus组件的按需引入,同时解决遇到的一些坑。 安装Element Plus…...
Android GreenDao 升级 保留旧表数据
Android GreenDao 升级 保留旧表数据 大川的川关注IP属地: 北京 0.2052019.08.05 11:54:36字数 270阅读 363 瓦力和伊娃 GreenDao升级库版本号之后,以前的旧数据没有了,为啥,因为GreenDao在升级的时候会删除旧库,创建新库&#…...
记一次证书站有趣的SQL注入
一、确定站点 按照以前文章中提到的寻找可进站测试的思路,找到了某证书站的一处站点,通告栏中写明了初始密码的结构,因此我们可通过信息搜集进入该站点(可以考虑去搜集比较老的学号,因为这样的账号要么被冻结,要么就是…...
1_初识pytorch
之前完全没有了解过深度学习和pytorch,但现在因为某些原因不得不学了。不得不感叹,深度学习是真的火啊。纯小白,有错的欢迎指正~ 参考视频:PyTorch深度学习快速入门教程(绝对通俗易懂!)【小土堆…...
c++typeid()的使用
用处: typeid()函数主要用来获取对应类型或者变量的类型信息,其返回一个std::type_info的对象,这个对象中存放了对应类型的具体信息。 所以typeid()函数就是获取一个type_info的类型,然后可以通过此类型来获取到相应的类型信息。 type_info的…...
【面向就业的Linux基础】从入门到熟练,探索Linux的秘密(十四)-租云服务器及配环境、docker基本命令
主要介绍了租云服务器和docker配置、基本命令!!! 文章目录 前言 一、云平台 二、租云服务器及安装docker 1.阿里云 2.安装docker 三、docker命令 将当前用户添加到docker用户组 镜像(images) 容器(container) 四、实战…...
实现一个全栈模糊搜索匹配的功能
提供一个全栈实现的方案,包括 Vue 3 前端、Express 后端和 MySQL 数据库的分类模糊搜索功能。让我们逐步来看: 1. 数据库设计 (MySQL) 首先,我们需要一个存储分类的表: CREATE TABLE categories (id INT AUTO_INCREMENT PRIMAR…...
智慧景区导览系统小程序开发
智慧景区导览系统小程序的开发是一个综合性的过程,旨在通过先进的技术手段提升游客的游览体验。以下是开发智慧景区导览系统小程序的主要步骤和关键点: 一、需求分析 市场调研:了解旅游市场的最新趋势和游客的实际需求,包括游客…...
HIVE调优方式及原因
3.HIVE 调优: 需要调优的几个方面: 1.HIVE语句执行不了 2.HIVE查询语句,在集群中执行时,数据无法落地 HIVE执行时,一开始语句检查没有问题,生成了多个JOB, …...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
