当前位置: 首页 > news >正文

Unity笔记:数据持久化的几种方式

正文

主要方法:

  • ScriptableObject
  • PlayerPrefs
  • JSON
  • XML
  • 数据库(如Sqlite)

1. PlayerPerfs

PlayerPrefs 存储的数据是全局共享的,它们存储在用户设备的本地存储中,并且可以被应用程序的所有部分访问。这意味着,无论在哪个场景、哪个脚本中,只要是同一个应用程序中的代码,都可以读取和修改 PlayerPrefs 中的数据。

这意味着耦合性的增加、安全性的降低。它适合存储少量的基本数据(比如玩家的偏好设置、游戏设置、游戏进度等),但不适合存储大量或复杂的数据结构。

注意:

  • 每次Set完数据要调用PlayerPrefs.Save()把数据写入磁盘。
  • Get有两个参数,第一个是键名,第二个是没找到时传入的默认值。
int highScore = 1000;
PlayerPrefs.SetInt("HighScore", highScore);
// 记得保存
PlayerPrefs.Save();// 没找到就返回3
int score = PlayerPrefs.GetInt("Score", 3);

2. ScriptableObject

ScriptableObject的值在播放模式之后不会恢复原样,会保留修改

可以用于只读和读写两种数据,不过原则上还是只用于只读数据。

ScriptableObject 并不依赖于游戏对象(GameObject),也不受场景加载和卸载的影响。它的生命周期是由 Unity 引擎管理的。

使用流程:

  1. 派生自ScriptableObject创建基类
  2. 实例化后由编辑器对实例进行配置
  3. 其他C#脚本使用某个实例
  4. 合理使用OnValidate()方法(这是ScriptableObject中的值更改时触发的事件,但是仅限在编辑器使用

下述代码在数值发生变化时触发定义的valueChanged事件。注意需要在其他脚本中向 valueChanged 事件添加侦听器才能响应

// 代码源自参考链接2
using UnityEngine;
using UnityEngine.Events;[CreateAssetMenu(fileName = "NewWeapon", menuName = "Game/Weapon")]
public class WeaponScriptableObject : ScriptableObject
{public string weaponName;public int damage;public Sprite icon;[SerializeField, Range(0, 100)]private int maxHealth;// Define a UnityEvent with no argumentspublic UnityEvent valueChanged;#if UNITY_EDITORprivate void OnValidate(){// This method is called in the Unity Editor whenever a value is changed.// Invoke the UnityEvent when values change.if (UnityEditor.EditorApplication.isPlaying){valueChanged.Invoke(); // Fire the UnityEvent}}
#endif
}

这里要注意的是类似于[CreateAssetMenu(fileName = "mySharedData", menuName = "SharedData/MySharedData", order = 1)]这样的东西,意思是:

  • fileName:新创建实例的默认文件名为"mySharedData"。
  • menuName:在“Assets/Create”菜单中显示的类型条目名称为"SharedData"下的"MySharedData"。
  • order:菜单项在“Assets/Create”菜单中的位置为1(显示靠前的优先级)

由于SO尽量存储运行时不更改的数据,所以要修改当前的生命值会考虑如下方法。此处PlayerXP实际上是个引用,在Unity中,当一个类的成员是另一个类的实例时,默认情况下它就是引用类型,不需要额外的标记(我是对比着[SerializeReference]来看,见下文 )

public class PlayerXP {public int XP = 100;
}public class PlayerData : ScriptableObject {public PlayerXP PlayerXP;
}
PlayerData playerData = GetComponent<PlayerData>();
playerData.PlayerXP.XP = 200;

注:引用类型的序列化通常会占用更多的存储空间和加载时间(性能降低)

3. 序列化:Json、XML与二进制

using UnityEngine;[System.Serializable]
public class PlayerData
{public string playerName;public int playerScore;
}

关于序列化:

  • 必须是public类,其中的字段或者属性必须是可序列化的
  • 类中的方法不会被序列化
  • 构造函数不可以被序列化

不可以序列化的数据类型:

  • 静态类或静态成员(Static Members)
  • 委托(Delegate)
  • 事件(Event)
  • 指针(Pointer)
  • 索引器(Indexers)

静态成员是属于整个类的,但是序列化和反序列化是构造一个类的实例的

// 保存
string json = JsonUtility.ToJson(sourceObject);
System.IO.File.WriteAllText("playerData.json", json);
// 读取
string json = System.IO.File.ReadAllText("playerData.json");
SomeClass loadedPlayer = JsonUtility.FromJson<SomeClass>(json);

json是字符串文本,XML是标记语言(本身还是文本),二进制就是01序列。二进制在数据存储和传输的效率、紧凑性和速度上占有优势(但丧失了内容的可读性)

二进制有很多种方案:

  • protobuf (Protocol Buffers,谷歌研发的一种二进制序列化格式)
  • MessagePack

我们可以在官方仓库找到使用说明Github - MessagePack-CSharp

注:几个含Serialize的相关属性

  • [Serializable]是一个 C# 中的特性,它告诉编译器这个类可以被序列化。
  • [SerializeReference] 是 Unity 2019.3 引入的新特性,用于处理多态对象的序列化,使得可以在 Inspector 窗口中为该字段分配任意继承自同一父类的对象。
  • [SerializeField](这个是把Private变量暴露到Inspector中的,跟上面那俩没关系)

注:标记为 [Serializable] 的类需要自行确保其内容是可序列化的。该标记的作用仅是告诉编译器这个类可以被序列化,但是不对内容做任何保证,如果存在不可被序列化的字段则会被忽略(不会引起报错)。此外还要避免类中存在循环引用(例如类 A 包含类 B 的实例,而类 B 又包含类 A 的实例)

// example
using UnityEngine;
using System;[Serializable]
public class Shape
{public float area;public virtual void Draw() { }
}[Serializable]
public class Circle : Shape
{public float radius;public override void Draw(){Debug.Log("Drawing a circle");}
}[Serializable]
public class Rectangle : Shape
{public float width;public float height;public override void Draw(){Debug.Log("Drawing a rectangle");}
}public class ShapeHolder : MonoBehaviour
{[SerializeReference]public Shape shape;
}

4. 数据库

数据库通常用于存储大量结构化数据,例如用户信息、游戏配置、游戏关卡数据、成就和统计信息等。相较于ScriptableObject、PlayerPrefs、JSON和XML文件,数据库的优势在于能够更灵活地管理和查询大量数据,并支持复杂的数据结构和关联查询。

数据库的优势包括:

  1. 数据结构灵活:数据库可以存储和管理复杂的数据结构,支持表与表之间的关联,适用于需要大量结构化数据的场景。
  2. 查询功能强大:数据库引擎提供强大的查询功能,可以进行复杂的数据筛选、排序和统计分析。
  3. 数据持久化:数据库中的数据可以持久保存,不受应用程序生命周期的影响,适用于长期存储和管理数据。
  4. 并发处理:数据库引擎通常支持并发处理,能够处理多个用户同时对数据进行读写的情况。
  5. 数据安全性:数据库可以提供数据加密、权限控制等安全功能,保护数据不被未授权访问。

参考与进一步阅读

PavCreations - Data persistence or how to save / load game data in Unity

Medium - A Beginner’s Guide to Storing and Retrieving Data in Unity

Medium - “How to Harness the Power of Scriptable Objects in Unity”

CSDN - 个人技术总结——Unity3D ScriptableObject实现多存档

CSDN - 【图文详解】Unity存储游戏数据的几种方法

相关文章:

Unity笔记:数据持久化的几种方式

正文 主要方法&#xff1a; ScriptableObjectPlayerPrefsJSONXML数据库&#xff08;如Sqlite&#xff09; 1. PlayerPerfs PlayerPrefs 存储的数据是全局共享的&#xff0c;它们存储在用户设备的本地存储中&#xff0c;并且可以被应用程序的所有部分访问。这意味着&#xf…...

MySQL 基础知识(八)之用户权限管理

目录 1 MySQL 权限管理概念 2 用户管理 2.1 创建用户 2.2 查看当前登录用户 2.3 修改用户名 2.4 删除用户 3 授予权限 3.1 授予用户管理员权限 3.2 授予用户数据库权限 3.3 授予用户表权限 3.4 授予用户列权限 4 查询权限 5 回收权限 1 MySQL 权限管理概念 关于 M…...

QT编写工具基本流程(自用)

以后有人让你写工具的时候&#xff0c;可以方便用这个模版及时提高工作效率&#xff0c;可以争取早点下班。包含库目录&#xff0c;头文件目录&#xff0c;输出目录以及翻译和部署&#xff0c;基本上都全了&#xff0c;也可以做收藏用用。 文章目录 1、创建项目Dialog Widget都…...

代码随想录算法训练营第三六天 | 无重叠区间、划分字母区间、合并区间

目录 无重叠区间划分字母区间合并区间 LeetCode 435. 无重叠区间 LeetCode 763.划分字母区间 LeetCode 56. 合并区间 无重叠区间 给定一个区间的集合 intervals &#xff0c;其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量&#xff0c;使剩余区间互不重叠…...

DP读书:《openEuler操作系统》(十)套接字 Socket 数据传输的基本模型

10min速通Socket 套接字简介数据传输基本模型1.TCP/IP模型2.UDP模型 套接字类型套接字&#xff08;Socket&#xff09;编程Socket 的连接1.连接概述(1)基本概念(2)连接状态(3)连接队列 2.建立连接3.关闭连接 socket 编程接口介绍数据的传输1. 阻塞与非阻塞2. I/O复用 数据的传输…...

抓住母亲节销售机会:Shopee 平台选品策略大揭秘

母亲节&#xff0c;作为一个重要的购物节日&#xff0c;为卖家带来了巨大的销售机会。在Shopee这样的电商平台上&#xff0c;如何通过有效的选品策略吸引消费者、提高销量呢&#xff1f;下面将介绍一些关键策略&#xff0c;帮助卖家在母亲节期间实现销售突破。 先给大家推荐一…...

Mysql如何优化数据查询方案

mysql做读写分离 读写分离是提高mysql并发的首选方案。 Mysql主从复制的原理 mysql的主从复制依赖于binlog&#xff0c;也就是记录mysql上的所有变化并以二进制的形式保存在磁盘上&#xff0c;复制的过程就是将binlog中的数据从主库传输到从库上。 主从复制过程详细分为3个阶段…...

SwiftUI 更自然地向自定义视图传递参数的“另类”方式

概览 在 SwiftUI 中&#xff0c;正是自定义视图让我们的 App 变得与众不同&#xff01;然而&#xff0c;除了传统的视图接口定义方式以外&#xff0c;我们其实还可以有更“银杏化”的选择。 如上图所示&#xff1a;对于 SubView 子视图所需的参数我们一开始并没有操之过急&…...

Word第一课

文章目录 1. 文件格式1.1 如何显示文件扩展名1.2 Word文档格式的演变1.3 常见的Word文档格式 3. 文档属性理解文档属性查看文档属性 1. 文件格式 1.1 如何显示文件扩展名 文档格式指的是文件的扩展名&#xff0c;例如下图 对于该文件&#xff0c;.docx就是文件扩展名&#x…...

【Vue3】路由传参的几种方式

路由导航有两种方式&#xff0c;分别是&#xff1a;声明式导航 和 编程式导航 参数分为query参数和params参数两种 声明式导航 query参数 一、路径字符串拼接(不推荐) 1.传参 在路由路径后直接拼接?参数名:参数值 &#xff0c;多组参数间使用&分隔。 <RouterLink …...

突破编程_C++_面试(高级特性(1))

面试题1&#xff1a;什么是线程以及它在并发编程中的作用是什么 线程&#xff08; Thread &#xff09;是操作系统能够进行运算调度的最小单位&#xff0c;它被包含在进程之中&#xff0c;是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流&#xff0c;一个进…...

django请求生命周期流程图,路由匹配,路由有名无名反向解析,路由分发,名称空间

django请求生命周期流程图 浏览器发起请求。 先经过网关接口&#xff0c;Django自带的是wsgiref&#xff0c;请求来的时候解析封装&#xff0c;响应走的时候打包处理&#xff0c;这个wsgiref模块本身能够支持的并发量很少&#xff0c;最多1000左右&#xff0c;上线之后会换成u…...

@ 代码随想录算法训练营第8周(C语言)|Day54(动态规划)

代码随想录算法训练营第8周&#xff08;C语言&#xff09;|Day54&#xff08;动态规划&#xff09; Day53、动态规划&#xff08;包含题目 ● 123.买卖股票的最佳时机III ● 188.买卖股票的最佳时机IV &#xff09; 123.买卖股票的最佳时机III 题目描述 给定一个数组&#…...

Flask 学习100-Flask-SocketIO 结合 xterm.js 实现网页版Xshell

前言 xterm.js 是一个使用 TypeScript 编写的前端终端组件,可以直接在浏览器中实现一个命令行终端应用。 可以实现 web-terminal 功能,类似于Xshell 操作服务器。 Flask-SocketIO 快速入门与使用基础参考前面这篇https://www.cnblogs.com/yoyoketang/p/18022139 前后端交互…...

Springboot AOP开发

Springboot AOP开发 一 AOP概述 AOP&#xff0c;即面向切面编程&#xff0c;简言之&#xff0c;面向方法编程。 针对方法&#xff0c;在方法的执行前或执行后使用&#xff0c;用于增强方法&#xff0c;或拓展。 二 AOP开发 1.引入 spring-boot-starter-aop 在SpringBoot项…...

office的excel中使用,告诉我详细的解决方案,如何变成转化为金额格式

在Office的Excel中&#xff0c;如果你想将名为"MEREFIELD"的公式结果转换为金额格式&#xff0c;你可以遵循以下详细步骤来实现&#xff1a; 书写MEREFIELD公式&#xff1a; 首先&#xff0c;在Excel中输入或确认你的MEREFIELD公式。例如&#xff0c;假设这个公式是用…...

灾后重建中GIS技术的关键作用与案例分析

地质灾害是指全球地壳自然地质演化过程中&#xff0c;由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。由于降水、地震等自然作用下&#xff0c;地质灾害在世界范围内频繁发生。我国除滑坡灾害外&#xff0c;还包括崩塌、泥石流、地面沉…...

java环境安装

java环境安装 一、官网下载&#xff1a; jdk&#xff0c;下载jdk&#xff0c;解压到D:\JAVA\Java\jdk目录下。 二、配置&#xff1a; 配置环境变量 鼠标右键我的电脑->属性->高级系统设置->环境变量->系统变量新建变量名JAVA_HOME&#xff0c;变量值为刚才解压的…...

如何在iStoreOS软路由系统中安装cpolar实现公网远程本地电脑桌面

文章目录 简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是&#xff1a;** 简介 软路由是PC的硬件加上路由系统来实现路由器的功能&#xff0c;也可以说是使用软件达成路由功能的路由器。 使用软路由控制局域网内计算机的好处&#xff1a…...

appium实现自动化测试原理

目录 1、Appium原理 1.1、Android Appium原理图文解析 1.1.2、原理详解 1.1.2.1、脚本端 1.1.2.2、appium-server 1.1.2.3、中间件bootstrap.jar 1.1.2.4、驱动引擎uiautomator 1.2、 IOS Appium原理 1、Appium原理 1.1、Android Appium原理图文解析 执行测试脚本全过…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...