数据持久化

PlayerPrefs相关

PlayerPrefs是Unity游戏引擎中的一个类,用于在游戏中存储和访问玩家的偏好设置和数据。它可以用来保存玩家的游戏进度、设置选项、最高分数等信息。PlayerPrefs将数据存储在本地文件中,因此可以在游戏重新启动时保持数据的持久性。

//PlayerPrefs的数据存储 类似于键值对存储 一个键对应一个值
//提供了存储3种数据的方法 int float string
//键: string类型
//值:int float string 对应3种API PlayerPrefs.SetInt("myAge", 18);
PlayerPrefs.SetFloat("myHeight", 177.5f);
PlayerPrefs.SetString("myName", "TonyChang"); //直接调用Set相关方法 只会把数据存到内存里
//当游戏结束时 Unity会自动把数据存到硬盘中
//如果游戏不是正常结束的 而是崩溃 数据是不会存到硬盘中的
//只要调用该方法 就会马上存储到硬盘中
PlayerPrefs.Save(); //PlayerPrefs是有局限性的 它只能存3种类型的数据
//如果你想要存储别的类型的数据 只能降低精度 或者上升精度来进行存储
bool sex = true;
PlayerPrefs.SetInt("sex", sex ? 1 : 0); //如果不同类型用同一键名进行存储 会进行覆盖
PlayerPrefs.SetFloat("myAge", 20.2f); //注意 运行时 只要你Set了对应键值对
//即使你没有马上存储Save在本地
//也能够读取出信息 //int
int age = PlayerPrefs.GetInt("myAge");
print(age);
//前提是 如果找不到myAge对应的值 就会返回函数的第二个参数 默认值
age = PlayerPrefs.GetInt("myAge", 100);
print(age); //float
float height = PlayerPrefs.GetFloat("myHeight", 1000f);
print(height); //string
string name = PlayerPrefs.GetString("myName");
print(name); //第二个参数 默认值 对于我们的作用
//就是 在得到没有的数据的时候 就可以用它来进行基础数据的初始化 //判断数据是否存在
if( PlayerPrefs.HasKey("myName") )
{
print("存在myName对应的键值对数据");
} //删除指定键值对
PlayerPrefs.DeleteKey("myAge");
//删除所有存储的信息
PlayerPrefs.DeleteAll();

PlayerPrefs中存储的数据存储在哪里?

PC端: PlayerPrefs 存储在 HKCU\Software[公司名称][产品名称] 项下的注册表中

其中公司和产品名称是 在“Project Settings”中设置的名称。

安卓: /data/data/包名/shared_prefs/pkg-name.xml

PlayerPrefs中数据的唯一性,PlayerPrefs中数据的唯一性是由key决定的,不同的key决定了不同的数据,同一个项目中如果不同数据key相同会造成数据丢失,要保证数据名称命名的唯一性规则。

优点:使用简单

缺点:存储数据类型有限、安全性差(直接找到在设备上的存储的位置查看设置)

PlayerPrefs存储工具类:

为了方便进行数据的存储,使用PlayerPrefs中进行存储方法的设置的存取!

主要实现功能是数据的读和数据的取~ 通过反射进行数据类型的获取,利用PlayerPrefs进行数据存储。

using System;
using System.Collections;
using System.Reflection;
using UnityEngine; namespace Framwork
{
/// <summary>
/// Playerprefs 存储类
/// </summary>
public class PlayerPrefsManager
{
private static PlayerPrefsManager instance=new PlayerPrefsManager(); public static PlayerPrefsManager Instance => instance; private PlayerPrefsManager()
{ } /// <summary>
/// 存取数据的方法
/// </summary>
/// <param name="obj">数据实体</param>
/// <param name="name">数据名称</param>
public void SaveData(object data, string keyName)
{
Type type = data.GetType();
FieldInfo[] infos = type.GetFields();
string tempKey="null";
FieldInfo tempInfo = null;
for (int i = 0; i < infos.Length; i++)
{
//获取数据数据类型
tempInfo = infos[i];
Debug.Log("Types==="+tempInfo);
//类的名字+类的类型 + 数据内容名字+数据类型
//作为存储的keyName键
tempKey = keyName + "_" + type.Name + "_" + tempInfo.Name
+ "_" + tempInfo.FieldType.Name;
SaveValue(tempInfo.GetValue(data),tempKey);
}
//进行值的获取
//tempInfo.GetValue(data);
PlayerPrefs.Save();
}
/// <summary>
/// 读取数据的类型
/// </summary>
/// <param name="type">要读取的数据类型</param>
/// <param name="name">要读取的数据名称</param>
/// <returns>返回数据实体</returns>
public object LoadData(Type type, string name)
{
//获取数据中的类型
FieldInfo[] infos = type.GetFields();
//创建存储数据信息的实体
object data = Activator.CreateInstance(type);
string tempName = null;
FieldInfo tempInfo = null;
for (int i = 0; i < infos.Length; i++)
{
tempInfo = infos[i];//数据结构中的数据名称
tempName = name + "_" + type.Name + "_" +tempInfo.Name+"_"
+tempInfo.FieldType.Name;//数据结构中的数据名称类型
//装载的容器 容器中的数据
//进行数据装载
tempInfo.SetValue(data,LoadValue(tempInfo.FieldType,tempName));
}
return data;
} /// <summary>
/// 进行具体的类型数据的存储
/// </summary>
/// <param name="data"></param>
/// <param name="keyName"></param>
private void SaveValue(object value, string keyName)
{
Type fieldType = value.GetType();
if (fieldType == typeof(int))
{
Debug.Log("存储int"+value);
PlayerPrefs.SetInt(keyName,(int)value);
}else if (fieldType == typeof(float))
{
Debug.Log("存储float"+value);
PlayerPrefs.SetFloat(keyName,(float)value);
}else if (fieldType == typeof(string))
{
Debug.Log("存储string"+value);
PlayerPrefs.SetString(keyName,value.ToString());
}
//对于List存储的设置
//根据存储的字段类型和IList是否是父子关系
else if(typeof(IList).IsAssignableFrom(fieldType))
{
//父类装子类
IList list=value as IList;
//存储元素数量
PlayerPrefs.SetInt(keyName,list.Count);
Debug.Log("存储List长度为"+list.Count);
int index = 0;
foreach (var obj in list)
{
//存储list列表中元素内容
//命名形式是 list名字+索引编号
//递归调用存储
SaveValue(obj,keyName+index);
index++;
}
}else if (typeof(IDictionary).IsAssignableFrom(fieldType))
{
IDictionary dictionary = value as IDictionary;
//存储数据个数
PlayerPrefs.SetInt(keyName,dictionary.Count);
Debug.Log("存储Dic长度为"+dictionary.Count);
int index = 0;
foreach (var key in dictionary.Keys)
{
//存储键
SaveValue(key,keyName+"_key_"+index);
//存储值
SaveValue(dictionary[key],keyName+"_value_"+index);
index++;
}
}//自定义数据类型的存储 进行解析
else
{
SaveData(value,keyName);
}
} private object LoadValue(Type type, string name)
{
if (type == typeof(int))
{
return PlayerPrefs.GetInt(name,0);
}else if (type == typeof(float))
{
return PlayerPrefs.GetFloat(name,0.0f);
}else if (type == typeof(string))
{
return PlayerPrefs.GetString(name,"");
}else if (typeof(IList).IsAssignableFrom(type))
{
//读取列表
int count = PlayerPrefs.GetInt(name);
IList tempList=Activator.CreateInstance(type) as IList;
for (int i = 0; i < count; i++)
{
//获取List中存储元素的类型 type.GetGenericArguments()[0]
tempList.Add(LoadValue(type.GetGenericArguments()[0],name+i));
}
return tempList;
}else if (typeof(IDictionary).IsAssignableFrom(type))
{
//进行对字典的读取
int count = PlayerPrefs.GetInt(name);
IDictionary tempDictionary=Activator.CreateInstance(type) as IDictionary;
for (int i = 0; i < count; i++)
{
tempDictionary.Add(LoadValue(type.GetGenericArguments()[0], name + "_key_" + i),
LoadValue(type.GetGenericArguments()[1], name + "_value_" + i));
}
return tempDictionary;
}
else
{
//读取自定义类成员的设置
return LoadData(type, name);
}
}
}
}

附:

测试脚本

using System.Collections.Generic;
using UnityEngine; namespace Framwork
{
//注意:
//1 自定义数据结构类型中要有有效的无参构造函数 public class PlayerInfo
{
public int age;
public string name;
public float height;
public int sex;//0是女 1是男 public ItemInfo ItemInfo;
//list存储测试
public List<int> list;
public Dictionary<int, string> dic; } public class ItemInfo
{
public int stu_no;//学号
public int stu_class;//班级 public ItemInfo()
{ }
public ItemInfo(int no,int classNo)
{
stu_no = no;
stu_class = classNo;
}
}
/// <summary>
/// 测试类
/// </summary>
public class TestPlayerPrefsTest:MonoBehaviour
{
private PlayerInfo playerInfo;
private PlayerInfo playerInfo1;
private void Start()
{
//读取数据
playerInfo = new PlayerInfo();
// Type fieldType = playerInfo.GetType();
playerInfo.age = 18;
playerInfo.name = "TonyChang";
playerInfo.height = 175.8f;
playerInfo.sex = 1;
playerInfo.ItemInfo = new ItemInfo(2001, 2); playerInfo.list = new List<int>(){1,5,6,8};
playerInfo.dic = new Dictionary<int, string>();
playerInfo.dic.Add(1,"Tony");
playerInfo.dic.Add(2,"Jeny");
playerInfo.dic.Add(3,"JayChou"); //进行数据保存
PlayerPrefsManager.Instance.SaveData(playerInfo,"Player1"); playerInfo1 = PlayerPrefsManager.Instance.LoadData(typeof(PlayerInfo), "Player1") as PlayerInfo; Debug.Log("age=="+playerInfo1.age);
Debug.Log("name=="+playerInfo1.name);
Debug.Log("sex=="+playerInfo1.sex);
Debug.Log("List[1]=="+playerInfo1.list[1]);
Debug.Log("Dic[1]=="+playerInfo1.dic[1]);
}
}
}

Unity学习笔记--数据持久化之PlayerPrefs的使用的更多相关文章

  1. tensorflow学习笔记——模型持久化的原理,将CKPT转为pb文件,使用pb模型预测

    由题目就可以看出,本节内容分为三部分,第一部分就是如何将训练好的模型持久化,并学习模型持久化的原理,第二部分就是如何将CKPT转化为pb文件,第三部分就是如何使用pb模型进行预测. 一,模型持久化 为 ...

  2. Adaptive AUTOSAR 学习笔记 15 - 持久化 Persistency

    本系列学习笔记基于 AUTOSAR Adaptive Platform 官方文档 R20-11 版本 AUTOSAR_EXP_PlatformDesign.pdf.作者:Zijian/TENG 原文地 ...

  3. [学习笔记]可持久化数据结构——数组、并查集、平衡树、Trie树

    可持久化:支持查询历史版本和在历史版本上修改 可持久化数组 主席树做即可. [模板]可持久化数组(可持久化线段树/平衡树) 可持久化并查集 可持久化并查集 主席树做即可. 要按秩合并.(路径压缩每次建 ...

  4. iOS学习之数据持久化详解

    前言 持久存储是一种非易失性存储,在重启设备时也不会丢失数据.Cocoa框架提供了几种数据持久化机制: 1)属性列表: 2)对象归档: 3)iOS的嵌入式关系数据库SQLite3: 4)Core Da ...

  5. Android学习_数据持久化

    数据持久化:将内存中的瞬时数据存储到设备中 1. 文件存储 存储一些简单的文本数据或二进制数据. 核心:Context类提供的openFileOutput()和openFileInput()方法,然后 ...

  6. Docker 学习笔记(持久化数据的备份,还原)

    假如我们应用程序需要一台 mssql 数据库来持久化数据,我们将 mssql 数据库运行于 Docker 容器中: docker run -d -p 1433:1433 -e "ACCEPT ...

  7. 微软企业库Unity学习笔记

    本文主要介绍: 关于Unity container配置,注册映射关系.类型,单实例.已存在对象和指出一些container的基本配置,这只是我关于Unity的学习心得和笔记,希望能够大家多交流相互学习 ...

  8. EXCEL 2010学习笔记 —— 数据透视表

    今天整理一下EXCEL2010 数据透视表的课程笔记,数据透视表可以对多组数据进行统计和整理,是一种基本的数据可视化工具. 记录6个方面的总结: 1.创建数据透视表 2.更改数据透视表的汇总方式 3. ...

  9. hibernate学习笔记之三 持久化的三种状态

    Hibernate持久化对象有3中状态,瞬时对象(transientObjects),持久化对象(persistentObjects),离线对象(detachedObjects) 下图显示持久化三种状 ...

  10. AMQ学习笔记 - 18. 持久化的测试

    概述 对持久化的有效性进行测试. 测试实例 测试实例 结果预测 持久化递送 重启ActiveMQ后,消息还在队列中 非持久化递送 重启ActiveMQ后,消息不在队列中 demo设计 jms-prod ...

随机推荐

  1. 关于python pycharm中输出的内容不全的解决办法

    import pandas as pd #设置显示的最大列.宽等参数,消除打印不完全中间的省略号 pd.set_option("display.width",1000) #加了这一 ...

  2. ubuntu安装rpm格式包

    首先,我们要安装alien这一软件: $sudo apt-get install alien ##alien默认没有安装,所以首先要安装它 $sudo alien xxxx.rpm ##将rpm转换为 ...

  3. 一种flink 作业提交失败的情况描述与原因排查

    遇到异常 2019-12-24 16:49:59,019 INFO org.apache.flink.yarn.YarnClusterClient - Starting client actor sy ...

  4. zabbix触发器标签提取监控项子字符串功能实现对应告警恢复

    0 实验环境 zabbix 6.0 1 监控项 1.1 监控项设置 通过zabbix agent自定义监控项,读取某文件内容模拟日志/trap告警,测试获取触发器标签中提取子字符串功能,以及相同标签的 ...

  5. 从 Pulsar Client 的原理到它的监控面板

    背景 前段时间业务团队偶尔会碰到一些 Pulsar 使用的问题,比如消息阻塞不消费了.生产者消息发送缓慢等各种问题. 虽然我们有个监控页面可以根据 topic 维度查看他的发送状态,比如速率.流量.消 ...

  6. GitOps 与 DevOps:了解关键差异,为企业做出最佳选择

    在软件开发领域,GitOps 和 DevOps 是加强协作和实现软件交付流程自动化的重要技术.虽然这两种模式都旨在提高软件开发生命周期的效率,但它们的核心原则和实施方式却各不相同. 本篇文章将帮助您了 ...

  7. Eolink 出席 QECon 大会,引领「AI+API」技术的革新浪潮

    7月28日-29日,第八届 QECon 质量效能大会在北京成功召开.大会聚焦"数生智慧,高质量发展新引擎",深入探讨如何利用数字化和智能化技术推动软件质量的发展,进而为高质量的经济 ...

  8. 为什么NoSQL不支持事务

    为什么NoSQL不支持事务 1. 背景 看书<Neo4j权威指南>的时候,发现个问题:日常的NoSQL都不支持事务(ACID). 2. 问题 事务对数据的存储过程是有利的,既然事情是有利的 ...

  9. 部署属于自己的New bing Ai

    该项目来源 https://github.com/adams549659584/go-proxy-bingai 项目体验地址 https://bing.vcanbb.top/web/#/ 项目介绍 基 ...

  10. 【问题解决】容器部署MySQL的数据在docker commit导出的镜像中丢失

    问题起因 最近公司有个甲方项目参加竞赛,要求在(基于kubeflow/arena)平台上部置应用,可以将MySQL打包在应用一起,也可以分开部署,没有提供volume相关的支持.大意是可以把初始好的数 ...