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

这篇具有很好参考价值的文章主要介绍了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 arguments
	public UnityEvent valueChanged;
	
	#if UNITY_EDITOR
	private 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存储游戏数据的几种方法文章来源地址https://www.toymoban.com/news/detail-826591.html

到了这里,关于Unity笔记:数据持久化的几种方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【Unity】二进制文件 数据持久化(修改版)【个人复习笔记/有不足之处欢迎斧正/侵删】

             变量的本质都是二进制 ,在内存中都以字节的形式存储着,通过sizeof方法可以看到常用变量类型占用的字节空间长度( 1byte = 8bit,1bit(位)不是0就是1 )         二进制文件读写的本质: 将各类型变量转换为字节数组,将字节数组直接存储到文件中 ,不仅可以节

    2024年04月17日
    浏览(16)
  • Unity数据持久化之PlayerPrefs

    Unity数据持久化之PlayerPrefs

    什么是数据持久化 数据持久化就是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。即将游戏数据存储到硬盘,硬盘中数据读取到游戏中,也就是传统意义上的存盘。 PlayerPrefs是什么 是 Unity 提供的可以用于存储读取玩家数据的公共类

    2024年02月19日
    浏览(9)
  • Unity之数据持久化——Json

    JavaScript对象简谱(JavaScript Object Notation) json是国际通用的一种轻量级的数据交换格式,主要在网络通讯中用于传输数据,或本地数据存储和读取,易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率 游戏中可以把游戏数据按照Json的格式标准存储在

    2023年04月20日
    浏览(10)
  • 【Unity学习日记03】数据持久化

    【Unity学习日记03】数据持久化

    这一篇只能说写了一部分,并没有把Unity里数据持久化的操作讲完整,之后可能是学到一点就记一点的模式。 数据持久化就是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。 人话版:将游戏数据存储到硬盘,硬盘中数据读取到游戏中,

    2024年02月12日
    浏览(8)
  • Unity PlayerPrefs 持久化数据存在哪

    Unity PlayerPrefs 持久化数据存在哪

    在游戏开发的过程中,我们经常需要存档相关的东西,称为数据的持久化。PlayerPrefs 就是Unity提供的用于本地数据持久化保存与读取的类。 PlayerPrefs会以键值对的方式存储在本地的注册表中。 1.存储数据 2.获取数据 3.删除数据 这些数据会存储在注册表中,打开注册表就能查看

    2024年02月16日
    浏览(13)
  • 【unity之数据持久化】-Unity公共类PlayerPrefs

    【unity之数据持久化】-Unity公共类PlayerPrefs

    👨‍💻个人主页 :@元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏 : unity数据存储 API大全图解 windows平台存储路径 HKCUSoftware[公司名称][产品名称] 项下的注册表中 公司和产品名称是 在“Project Settings”中设

    2024年02月04日
    浏览(33)
  • 【Unity】数据持久化路径Application.persistentDataPath

    【Unity】数据持久化路径Application.persistentDataPath

    今天突然想到这个路径Application.persistentDataPath,热更的重要路径,该文件夹可读可写,在移动端唯一一个可读写操作的文件夹。 移动端可以将本地的资源(资源MD5值配置表)等一些文件放到StreamingAssets文件夹下,通过Copy到persistentDataPath下与服务器的版本文件配置表作比对,

    2023年04月10日
    浏览(15)
  • K8s 持久化存储有几种方式?一文了解本地盘/CSI 外接存储/K8s 原生存储的优缺点

    K8s 持久化存储有几种方式?一文了解本地盘/CSI 外接存储/K8s 原生存储的优缺点

    当今云原生环境中,Kubernetes(K8s)已成为既定的容器编排工具。随着 K8s 的普及,存储也成为 K8s 用户关注的一个重要问题:为了满足不同的场景需求,K8s 可以支持基于不同架构的多种存储方案。这些方案间有什么区别?用户应如何选择? 本文将从架构角度出发,详细介绍本

    2024年02月10日
    浏览(10)
  • 持续集成部署-k8s-数据持久化-基本存储方式

    关于k8s 数据持久化,可以先看下官方的介绍:

    2024年02月13日
    浏览(18)
  • 持续集成部署-k8s-数据持久化-高级存储方式

    持久卷(PersistentVolume,PV) 是集群中的一块存储,可以由管理员事先制备, 或者使用

    2024年02月16日
    浏览(15)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包