[Unity存档系统]简单介绍Unity常见存档系统之一PlayerPrefs以及使用方法

2023-10-29

学习目标:

  如果你和我同样苦恼于游戏相关的数据怎么存储与读取,那么不妨看看这个up主有关Unity存档系统的教程。[Unity] 存档系统 Part 1 | PlayerPrefs | Unity初学者系列教程 | 数据存取 | 存档读档 | Save&Load_哔哩哔哩_bilibili在本视频中你将学到Unity引擎中三种常见的数据存储方式中的第一种:PlayerPrefs主要内容:什么是PlayerPrefs如何使用PlayerPrefsPlayerPrefs的优缺点以及适用范围构建一个基于PlayerPrefs的基础数据存取系统Unity存档系统第二部分 - JSON:BV1Cb4y1b71G————————————————————你好啊,我是阿严,一个小小的独立游戏开发者https://www.bilibili.com/video/BV1nQ4y1z7pZ/?spm_id_from=333.788.recommend_more_video.-1

这里我将up主讲到的内容作为笔记,先给大伙开个头介绍PlayerPrefs。

 


学习内容:

  根据官网的API的定义,`PlayerPrefs`是一个在游戏会话之间存储玩家首选项的类。它可以将字符串、浮点和整数值存储到用户的平台注册表中。由此可见,他能存储string,int,float类型的数据到计算机的数据表中,这就注定了它只能存储简单的数据,玩家的偏好选项例如音量设置等,下面不妨通过一个项目简单了解一下怎么使用。

   这里使用的是up主的GitHub素材,有一个现成的场景,这里我想重头开始写,把Player和UI上挂载的脚本全部删了,再新建一个NewPlayer然后就到了脚本的时间

首先是NewPlayer脚本,我们创建两个私有函数用啦保存和读取PlayerPrefs上的数据,两个public函数用来给按钮的点击事件。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SaveSystemTur
{
    public class NewPlayerData : MonoBehaviour
    {
        private const string PLAYER_DATA_KEY = "PlayerData";
        #region Fields
        [SerializeField] string playerName = "";
        [SerializeField] int coin = 0;
        [SerializeField] int level = 0;

        [System.Serializable]
        class SaveData
        {
            public string playerName;
            public int playerLevel;
            public int playerCoin;
            public Vector3 playerPosition;
        }

        #endregion

        #region Propertries

        public string PlayerName => playerName;
        public int Coin => coin;
        public int Level => level;

        public Vector3 Position => transform.position;
        #endregion

        #region Save And Load
        public void Save()
        {
            SaveByPlayerPrefs();
        }
        public void Load()
        {
            LoadFromPlayerPrefs();
        }
        #region PlayerPrefs
        void SaveByPlayerPrefs()
        {
            PlayerPrefs.SetInt("PlayerLevel", level);
            PlayerPrefs.SetInt("PlayerCoin", coin);

            PlayerPrefs.SetFloat("PlayerPositionX", transform.position.x);
            PlayerPrefs.SetFloat("PlayerPositionY", transform.position.y);
            PlayerPrefs.SetFloat("PlayerPositionZ", transform.position.z);
        }

        

        void LoadFromPlayerPrefs()
        {
            
            playerName = PlayerPrefs.GetString("PlayerName", "Somebody");

            level = PlayerPrefs.GetInt("PlayerLevel");
            coin = PlayerPrefs.GetInt("PlayerCoin");

            transform.position = new Vector3(PlayerPrefs.GetFloat("PlayerPositionX"), PlayerPrefs.GetFloat("PlayerPositionY"), PlayerPrefs.GetFloat("PlayerPositionZ"));
        }

        

        
}

这里涉及到的有PlayerPrefs.Set****(),PlayerPrefs.Get****().

然后再UI函数中

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace SaveSystemTur
{
    public class NewUIController : MonoBehaviour
    {
        #region Propertries
        [Header("============ Text ==========")]
        [SerializeField] Text playerNameText;
        [SerializeField] Text playerLevelText;
        [SerializeField] Text playerCoinText;
        [SerializeField] Text playerPositionX;
        [SerializeField] Text playerPositionY;
        [SerializeField] Text playerPositionZ;

        [Header("============ Button ========")]
        [SerializeField] Button saveButton;
        [SerializeField] Button loadButton;

        [SerializeField] NewPlayerData newPlayerData;
        #endregion
        void Start()
        {
            saveButton.onClick.AddListener(newPlayerData.Save);
            loadButton.onClick.AddListener(newPlayerData.Load);
        }

        void Update()
        {
            playerNameText.text = newPlayerData.PlayerName;
            playerLevelText.text = newPlayerData.Level.ToString();
            playerCoinText.text = newPlayerData.Coin.ToString();
            playerPositionX.text = newPlayerData.Position.x.ToString();
            playerPositionY.text = newPlayerData.Position.y.ToString();
            playerPositionZ.text = newPlayerData.Position.z.ToString();
        }
    }
}

 记得挂载好参数

点击Win+R进入命令行 ,输入以下命令。找到你Unity的目录,

 

当你运行游戏的时候并且输入数据并且保存的时候在你的游戏项目目录里面,就会有注册的新数据,这里我就不演试了,而且当你退出游戏并且重新游戏的时候,你点击Load,之前注册的数据就又会返回了。

简单的数据存储已经实现了,我们还可以删除已经存储的PlayerPrefs,而这个功能Unity已经为我们提供了

 

    可能你和我会想,一条条的存储和读取数据,这个是否有点。。。。代码的耦合性显而易见的搞。因此我们要创建一个SaveSystem的脚本,并用一个普通的类来实现,我们先把数据转化为文本形式(string类型),然后用PlayerPrefs的SetString像存储键值对一般,再用Save()函数保存,读取则直接返回键以及一个空值

namespace SaveSystemTur
{
    public static  class SaveSystem
    { 
#region PlayerPrefs
        public static void SaveByPlayerPrefs(string key,object data)
        {
            var json = JsonUtility.ToJson(data,true);//true即转化为json的文本格式

            PlayerPrefs.SetString(key, json);
            PlayerPrefs.Save();

#if UNITY_EDITOR
            Debug.Log("成功保存数据到PlayerPrefs");
#endif
        }


        public static string LoadFromPlayerPrefs(string key)
        {
            return PlayerPrefs.GetString(key,null);
        }
        #endregion
     }
}

   我们使用新的扩展方式JsonUtility来实现,通过FromJSON<T>以及ToJSON,我们可以将untiy可以支持的序列化类转化为json格式

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SaveSystemTur
{
    public class NewPlayerData : MonoBehaviour
    {
        private const string PLAYER_DATA_KEY = "PlayerData";

        #region Fields
        [SerializeField] string playerName = "";
        [SerializeField] int coin = 0;
        [SerializeField] int level = 0;

        [System.Serializable]
        class SaveData
        {
            public string playerName;
            public int playerLevel;
            public int playerCoin;
            public Vector3 playerPosition;
        }

        #endregion

        #region Propertries

        public string PlayerName => playerName;
        public int Coin => coin;
        public int Level => level;

        public Vector3 Position => transform.position;
        #endregion

        #region Save And Load
        public void Save()
        {
            SaveByPlayerPrefs();
        }
        public void Load()
        {
            LoadFromPlayerPrefs();
        }

        #region PlayerPrefs

        void SaveByPlayerPrefs()
        {
            SaveData saveData = SavingData();
            SaveSystem.SaveByPlayerPrefs(PLAYER_DATA_KEY, saveData); //把savedata的值存储到键对中
        }

        private SaveData SavingData() //对要存储的数据进行初始化
        {
            var saveData = new SaveData();
            saveData.playerName = playerName;
            saveData.playerCoin = coin;
            saveData.playerLevel = level;
            saveData.playerPosition = transform.position;

            return saveData;
        }

        void LoadFromPlayerPrefs()
        {
            var json = SaveSystem.LoadFromPlayerPrefs(PLAYER_DATA_KEY); //string类型
            var saveData = JsonUtility.FromJson<SaveData>(json); //SaveData类型
            LoadData(saveData); //返回数据给我们所需要保存的数据
        }

        private void LoadData(SaveData saveData)
        {
            playerName = saveData.playerName;
            level = saveData.playerLevel;
            coin = saveData.playerCoin;
            transform.position = saveData.playerPosition;
        }

        #endregion

        #endregion


    }
}

最后因我们有键值对,因此想删除对应的PlayerPrefs找到对应的键即可

在NewPlayerData脚本中

[UnityEditor.MenuItem("Developer/Delete Player Data Prefs")]
        public static void DeletePlayerDataPrefs()
        {
            //PlayerPrefs.DeleteAll();
            PlayerPrefs.DeleteKey(PLAYER_DATA_KEY);
        }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[Unity存档系统]简单介绍Unity常见存档系统之一PlayerPrefs以及使用方法 的相关文章

  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 编译的表达式树会泄漏吗?

    根据我的理解 JIT 代码在程序运行时永远不会从内存中释放 这是否意味着重复调用 Compile 表达式树上会泄漏内存吗 这意味着仅在静态构造函数中编译表达式树或以其他方式缓存它们 这可能不那么简单 正确的 他们可能是GCed Lambda
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • Bing 地图运行时错误 Windows 8.1

    当我运行带有 Bing Map 集成的 Windows 8 1 应用程序时 出现以下错误 Windows UI Xaml Markup XamlParseException 类型的异常 发生在 DistanceApp exe 中 但未在用户
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反
  • 不同类型的指针可以互相分配吗?

    考虑到 T1 p1 T2 p2 我们可以将 p1 分配给 p2 或反之亦然吗 如果是这样 是否可以不使用强制转换来完成 或者我们必须使用强制转换 首先 让我们考虑不进行强制转换的分配 C 2018 6 5 16 1 1 列出了简单赋值的约束

随机推荐

  • linux usb状态监测,linux下 USB动态监测 hotplug事件监测

    总体规划 使用netlink接口向内核注册hotplug事件通知 获取事件通知后进行相关动作如 Action add 挂载或 action remove 卸载 使用Socket IPC机制向需要响应USB热拔插事件的应用程序报告 功能包括
  • Sourcegraph部署安装和使用

    Sourcegraph是什么 方便的搜索代码 方便的跳转和查看函数 最简单的安装方式 然后你的github就会变成如此 点击小按钮后 你的项目去到了这么个地方 然后你就能尽情的使用其强大的查看代码的功能了 不过事情并没有那么简单 有的人会有
  • Nginx配置文件

    Nginx 服务器安装及配置文件详解 Nginx 服务器安装及配置文件详解 菜鸟教程 Nginx配置文件主要分成四部分 main 全局设置 server 主机设置 upstream 上游服务器设置 主要为反向代理 负载均衡相关配置 设定负载
  • 好用的截图工具Snipaste使用教程

    在日常使用电脑的过程中经常会用到截图操作 今天要跟大家分享的是好用的截图工具Snipaste使用教程 下载安装 到官网下载软件 下载完成后无需安装 直接打开 Snipaste exe 文件就可以使用了 截图 截图默认快捷键是 F1 按下后界
  • 电脑文件怎么复制到服务器,电脑上文件怎样粘贴复制到云服务器

    电脑上文件怎样粘贴复制到云服务器 内容精选 换一换 本方式建议用于非生产系统 本方式通过使用云硬盘备份服务或云服务器备份服务 对SAP HANA的一个或多个卷执行快照 再将卷快照创建成备份 自动上传到华为云OBS 具体方案如图1所示 本方式
  • c++ functor用处!!!

    某些特殊场景 函数中包含一些要赋的值 但是函数只能传入一个参数 例如使用count if 来得到长度大于len的字符的个数 class ShorterThan public explicit ShorterThan int maxLengt
  • Cadence 17.2 Padstack Editor入门指南(2)

    Cadence 17 2 Pad Editor入门指南 2 创建自定义焊盘及封装 Pad Editor与Allegro PCB Designer相互配合 可以做出各种类型的封装 当我们需要制作相对简单的封装时 可以用Pad Editor图形
  • faiss简介及示例

    faiss简介及示例 原文 https blog csdn net kanbuqinghuanyizhang article details 80774609 版权声明 本文为博主原创文章 未经博主允许不得转载 https blog csd
  • LLC和MAC子层的应用

    计算机局域网标准IEEE802 由于局域网只是一个计算机通信网 而且局域网不存在路由选择问题 因此它不需要网络层 而只有最低的两个层次 然而局域网的种类繁多 其媒体接入控制的方法也各不相同 为了使局域网中的数据链路层不致过于复杂 就应当将局
  • 多线程:线程内局部变量

    ThreadLocal类 该类提供了线程内局部 thread local 变量 好比有两个窗口 两个线程 一个窗口可以拿饮料 一个窗口可以拿食物 现在有多个人要来拿东西 如果在饮料窗口有的人拿到了饮料 有的人拿到了不该拿的食物 就说明线程之
  • 【性能测试】第一篇 性能测试概述

    性能测试的介绍 性能测试 通常意义上都是说的服务器性能 性能 内存 cpu 电量 流量 流畅度 为什么要进行性能测试 1 业务需求 例 电商双11活动 微信春晚抢红包 12306春运订票 当前服务器配置是否支持20000人同时使用 技术选型
  • 数据标注对新零售的意义及人工智能在新零售领域的应用?

    数据标签对于新零售至关重要 因为它构成了训练和部署人工智能 AI 和机器学习 ML 模型的基础 在新零售的背景下 数据标签涉及对数据进行分类 标记或注释以使其能够被机器理解的过程 然后 这些标记数据用于训练人工智能算法来识别模式 做出预测并
  • 深入浅出!十三张图带你从源码了解SpringBoot启动流程!实战篇

    前言 一位小伙伴准备了许久的阿里Java面试 原以为能够顺利拿下offer 但在第三面还是被摁在地上反复摩擦 丧气一段时间后 小伙伴调整了心态重新尝试了一下 最终拿下了offer 今天小编把这位小伙伴遇到的面试题分享出来 希望能对即将面试的
  • 元强化学习系列(1)之:元学习入门基础

    元强化学习三境界 统计学是人工智能开始发展的一个基础 古老的人们从大量的数据中发现七所存在的规律 在以统计学为基础的 机器学习 machine learning 时代 复杂一点的分类问题效果就不好了 深度学习 Deep Learning 的
  • 软件测试进阶之自动化测试

    扼要 1 了解软件自动化测试的概念 什么情况下进行软件自动化测试 2 了解软件自动化测试的分类 3 了解自动化测试的好处与确定 软件自动化测试 顾名思义就是使用软件对需要测试的软件进行机械地执行测试 自动化测试分类 自动化测试 通常分UI自
  • SPSS数据拆分(分组)

    本文中以CPI 消费者价格指数 分析为例 数据中分别给出了全国31个省市 在12个月 2018年8月 2019年7月 中的CPI 数据由 中国统计局 官网导出 引入 当我们从Excel文件导入数据后 如下图左 当我们分析的时候 我们希望得到
  • echarts 自定义鼠标悬停展示

    tooltip trigger axis formatter function params let htmlStr for let i 0 i lt params length i const param params i const x
  • 100天精通Python(可视化篇)——第82天:matplotlib绘制不同种类炫酷散点图参数说明+代码实战(二维散点图、三维散点图、散点图矩阵)

    文章目录 专栏导读 0 前言 1 参数说明 2 两主特征 二维散点图 1 普通散点图 2 文字标签散点图 3 带颜色映射的散点图 4 ArcGIS散点图 5
  • 微信小程序总结(2)- 需求分析

    在真正进入代码开发之前 很重要的一步就是进行需求分析 用户画像 这款微信小程序的主要用户是谁 是年轻人 中年人 还是老年人 是男生 还是女生 是工薪阶层 还是企业主 是金融理财 还是在线票务 在进行一定范围的样本调查后 可以得出一个精准的用
  • [Unity存档系统]简单介绍Unity常见存档系统之一PlayerPrefs以及使用方法

    学习目标 如果你和我同样苦恼于游戏相关的数据怎么存储与读取 那么不妨看看这个up主有关Unity存档系统的教程 Unity 存档系统 Part 1 PlayerPrefs Unity初学者系列教程 数据存取 存档读档 Save Load 哔