一、数据持久化概念
数据持久化就是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。
简单来说:就是将游戏数据存储到硬盘,将硬盘中数据读取到游戏中,也就是传统意义上的存盘。
是Unity提供的可以用于存储读取玩家数据的公共类。
二、PlayerPrefs
(一)PlayerPrefs的基本方法
1.存储相关
PlayerPrefs的数据存储 类似于键值对存储 一个键对应一个值
提供了存储3中数据的方法 int float string
键:string类型
值:int float string 对应3种API
直接
PlayerPrefs.SetInt(“myAge”, 18);//存入内存
PlayerPrefs.SetFloat(“myHeight”, 229.5f);
PlayerPrefs.SetString(“myName”, “姚明”);直接调用Set相关方法 只会把数据存到内存中
当游戏结束时 Unity会自动把数据存到硬盘中
如果游戏报错崩溃,数据不会存到硬盘中
PlayerPrefs.Save();
调用该方法,会马上存储到硬盘中
局限性:只能存3种类型数据
若想存储其他,只能降低会提高精度来存储
布尔类型
bool sex = true;
PlayerPrefs.SetInt(“sex” , sex ? 1 : 0);
如果类型用同一键名存储,会覆盖
PlayerPrefs.SetFloat(“myAge”,20.2f);
2.读取相关
运行时,只要Set对应键值对,即使没有马上Save到本地,也可以读取信息
int age = PlayerPrefs.GetInt(“myAge”);//如果找不到 返回默认值0
age = PlayerPrefs.GetInt(“myAge” , 100 );
如果找不到myAge对应的值,就会返回函数的第二个参数 默认值
float height = PlayerPrefs.GetFloat(“myHeight” , 1000f);
float name= PlayerPrefs.GetString(“myname” , “姚明”);
判断数据是否存在
PlayerPrefs.HasKey(“myName”);
3.删除数据
删除指定键值对
PlayerPrefs.DeleteKey();
删除所有存储的信息
PlayerPrefs.DeleteAll();
4.练习1
现在有玩家信息类,有名字,年龄,攻击力,防御力等成员。另有装备信息类,装备类中有id,数量两个成员。
现在为其封装两个方法,一个用来存储数据,一个用来读取数据
注意,装备是个list,所以存储时候需要遍历
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Item
{
public int id;
public int num;
}
public class Player
{
public string name;
public int age;
public int atk;
public int def;
//拥有的装备信息
public List<Item> itemList;
//这个变量 是一个 存储和读取的一个唯一key标识
private string keyName;
/// <summary>
/// 存储数据
/// </summary>
public void Save()
{
PlayerPrefs.SetString(keyName +"_name", name);
PlayerPrefs.SetInt(keyName + "_age", age);
PlayerPrefs.SetInt(keyName + "_atk", atk);
PlayerPrefs.SetInt(keyName + "_def", def);
//存储有多少个装备
PlayerPrefs.SetInt(keyName + "_ItemNum", itemList.Count);
for (int i = 0; i < itemList.Count; i++)
{
//存储每一个装备的信息
PlayerPrefs.SetInt(keyName + "_itemID" + i, itemList[i].id);
PlayerPrefs.SetInt(keyName + "_itemNum" + i, itemList[i].num);
}
PlayerPrefs.Save();
}
/// <summary>
/// 读取数据
/// </summary>
public void Load(string keyName)
{
//记录你传入的标识
this.keyName = keyName;
name = PlayerPrefs.GetString(keyName + "_name", "未命名");
age = PlayerPrefs.GetInt(keyName + "_age", 18);
atk = PlayerPrefs.GetInt(keyName + "_atk", 10);
def = PlayerPrefs.GetInt(keyName + "_def", 5);
//得到有多少个装备
int num = PlayerPrefs.GetInt(keyName + "_ItemNum", 0);
//初始化容器
itemList = new List<Item>();
Item item;
for (int i = 0; i < num; i++)
{
item = new Item();
item.id = PlayerPrefs.GetInt(keyName + "_itemID" + i);
item.num = PlayerPrefs.GetInt(keyName + "_itemNum" + i);
itemList.Add(item);
}
}
}
public class Lesson1_Exercises : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
//现在有玩家信息类,有名字,年龄,攻击力,防御力等成员
//现在为其封装两个方法,一个用来存储数据,一个用来读取数据
//Player p = new Player();
//p.Load();
//print(p.name);
//print(p.age);
//print(p.atk);
//print(p.def);
//p.name = "唐老狮";
//p.age = 22;
//p.atk = 40;
//p.def = 10;
改了过后存储
//p.Save();
Player p = new Player();
p.Load("Player1");
p.Save();
Player p2 = new Player();
p2.Load("Player2");
p.Save();
//装备信息
//print(p.itemList.Count);
//for (int i = 0; i < p.itemList.Count; i++)
//{
// print("道具ID:" + p.itemList[i].id);
// print("道具数量:" + p.itemList[i].num);
//}
为玩家添加一个装备
//Item item = new Item();
//item.id = 1;
//item.num = 1;
//p.itemList.Add(item);
//item = new Item();
//item.id = 2;
//item.num = 2;
//p.itemList.Add(item);
}
// Update is called once per frame
void Update()
{
}
}
(二)PlayerPrefs在不同平台的存储位置
1.不同平台存储位置不同
Window
//PlayerPrefs存储在
// HKCU\Software\[公司名称]\产品名称]项下的注册表中
//其中公司和产品名称是在“Project settings”中设置的名称。
//运行regedit
//HKEY_CURRENT_USER/ /SOFTWARE
//Unity
//UnityEditor//公司名称//产品名称
Android
/data/data/包名/shared_prefs/pkg-name.xml
IOS
/Library/Preferences/[应用ID].plist
2.PlayerPrefs数据唯一性
//PlayerPrefs中不同数据的唯一性
//是由key决定的,不同的key决定了不同的数据
//同一项目中 如果不同数据key相同 会造成数据丢失
//要保证数据不丢失就要建立一个保证key唯一的规则
3.练习2
要在游戏中做一个排行榜功能,排行榜主要记录玩家名(可重复),玩家得分,玩家通关时间,请用PlayerPrefs存储读取排行榜相关信息
注意:这个名字可以重复就代表了不能单独的将名字当做key
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 排行榜具体信息
/// </summary>
public class RankListInfo
{
public List<RankInfo> rankList;
public RankListInfo()
{
Load();
}
/// <summary>
/// 新加排行榜信息
/// </summary>
public void Add(string name , int score, int time)
{
rankList.Add(new RankInfo(name, score, time));
}
public void Save()
{
//存储有多少条数据
PlayerPrefs.SetInt("rankListNum", rankList.Count);
for (int i = 0; i < rankList.Count; i++)
{
RankInfo info = rankList[i];
PlayerPrefs.SetString("rankInfo" + i, info.playerName);
PlayerPrefs.SetInt("rankScore" + i, info.playerScore);
PlayerPrefs.SetInt("rankTime" + i, info.playerTime);
}
}
private void Load()
{
int num = PlayerPrefs.GetInt("rankListNum", 0);
rankList = new List<RankInfo>();
for (int i = 0; i < num; i++)
{
RankInfo info = new RankInfo(PlayerPrefs.GetString("rankInfo" + i),
PlayerPrefs.GetInt("rankScore" + i),
PlayerPrefs.GetInt("rankTime" + i));
rankList.Add(info);
}
}
}
/// <summary>
/// 排行榜单条信息
/// </summary>
public class RankInfo
{
public string playerName;
public int playerScore;
public int playerTime;
public RankInfo(string name, int score, int time)
{
playerName = name;
playerScore = score;
playerTime = time;
}
}
public class Lesson2_Exercises : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
#region 练习题一
//将知识点一中的练习题,改为可以支持存储多个玩家信息
#endregion
#region 练习题二
//要在游戏中做一个排行榜功能
//排行榜主要记录玩家名(可重复),玩家得分,玩家通关时间
//请用PlayerPrefs存储读取排行榜相关信息
RankListInfo rankList = new RankListInfo();
print(rankList.rankList.Count);
for (int i = 0; i < rankList.rankList.Count; i++)
{
print("姓名" + rankList.rankList[i].playerName);
print("分数" + rankList.rankList[i].playerScore);
print("时间" + rankList.rankList[i].playerTime);
}
rankList.Add("唐老狮", 100, 99);
rankList.Save();
#endregion
}
// Update is called once per frame
void Update()
{
}
}
(三)利用反射结合PlayerPrefs制作通用存储工具