一、基本知识
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson1_PlayerPrefs : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
#region 知识点一 PlayerPrefs是什么
//是Unity提供的可以用于存储读取玩家数据的公共类
#endregion
#region 知识点二 存储相关
//PlayerPrefs的数据存储 类似于键值对存储 一个键对应一个值
//提供了存储3种数据的方法 int float string
//键:string类型
//值: int float string 对应3种API
PlayerPrefs.SetInt("myAge", 18);
PlayerPrefs.SetFloat("myHeight", 177.5f);
PlayerPrefs.SetString("myName", "唐老师");
//直接调用Set相关方法 只会把数据存到内存里
//当游戏结束时 Unity会自动把数据存到硬盘中
//如果游戏不是正常结束的 而是崩溃 数据是不会存到硬盘中的
//只要调用该方法 就会马上存储到硬盘中
PlayerPrefs.Save();
//PlayerPrefs是有局限性的 它只能存3种类型的数据
//如果你想要存储别的类型的数据 只能降低精度 或者上升精度来进行存储
bool sex = true;
PlayerPrefs.SetInt("sex", sex ? 1 : 0);
//如果不同类型用同一键名进行存储 会进行覆盖
PlayerPrefs.SetFloat("myAge", 20.2f);
#endregion
#region 知识点三 读取相关
//注意 运行时 只要你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对应的键值对数据");
}
#endregion
#region 知识点四 删除数据
//删除指定键值对
PlayerPrefs.DeleteKey("myAge");
//删除所有存储的信息
PlayerPrefs.DeleteAll();
#endregion
}
// Update is called once per frame
void Update()
{
}
//总结:
// Set
// Get
// HasKey
// Del
}
二、示例
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("itemID"+i, itemList[i].id); PlayerPrefs.SetInt("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() { #region 练习题一 //现在有玩家信息类,有名字,年龄,攻击力,防御力等成员 //现在为其封装两个方法,一个用来存储数据,一个用来读取数据 //Player p = new Player(); //p.Load(); //print(p.name); //print(p.age); //print(p.atk); //print(p.def); //p.name = "唐老师"; //p.age = 10; //p.atk = 40; //p.def = 10; //改了过后存储 //p.Save(); #endregion #region 练习题二 //现在有装备信息类,装备类中有id,数量两个成员 //上一题的玩家类中包含一个List存储了拥有的所有装备信息 //请在上一题的基础上,把装备信息的存储和读取加上 Player p = new Player(); p.Load("Player1"); p.Save(); Player p2 = new Player(); p2.Load("Player2"); p.Save(); // p.Load(); //装备信息有多少个 //print(p.itemList.Count); //for (int i = 0; i < p.itemList.Count; i++) //{ // print("道具ID:"+p.itemList[i].id); // print("道具数量Num:"+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); //p.Save(); #endregion } // Update is called once per frame void Update() { } }
三、不同平台的存储位置
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson2_SaveWhere : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
#region 知识点一 PlayerPrefs存储的数据存在哪里?
//不同平台存储位置不一样
#region Windows
//PlayerPrefs 存储在
//HKCU\Software\[公司名称]\[产品名称] 项下的注册表中
//其中公司和产品名称是 在"Project Settings"中设置的名称
//运行 regedit
//HKEY_CURRENT_USER
//SOFTWARE
//Unity
//UnityEditor
//公司名称
//产品名称
#endregion
#region Android
// /data/data/包名/shared_prefs/pkg-name.xml
#endregion
#region IOS
// /Library/Preferences/[应用ID].plist
#endregion
#endregion
#region 知识点二 PlayerPrefs数据唯一性
//PlayerPrefs中不同数据的唯一性
//是由Key决定的,不同的Key决定了不同的数据
//同一项目中 如果不同数据Key相同 会造成数据丢失
//要保证数据不丢失就要建立一个保证Key唯一的规则
#endregion
}
// Update is called once per frame
void Update()
{
}
}
四、实战
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 排行榜具体信息
/// </summary>
public class RankListInfo
{
public List<RankInfo> rankList;
public RankListInfo()
{
Load();
}
/// <summary>
/// 新加排行榜信息
/// </summary>
/// <param name="name"></param>
/// <param name="score"></param>
/// <param name="time"></param>
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)
{
this.playerName = name;
this.playerScore = score;
this.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()
{
}
}
五、缺点
重复工作量繁多
自定义数据类,都需要自己去实现存储读取的功能
而且代码的相似度极高
数据容易被修改
只要找到文件位置,就可以轻易的进行数据修改