> 技术文档 > 数据持久化--PlayerPrefs

数据持久化--PlayerPrefs


PlayerPrefs是什么

在 Unity 中,PlayerPrefs 是一个用于存储和读取游戏偏好设置(如音量、最高分、游戏进度等)的内置类。它提供了一种简单的键值对存储方式,支持三种基本数据类型:intfloat 和 string,并会将数据持久化到本地文件系统。

支持的数据类型

PlayerPrefs 直接支持三种基础数据类型(底层都是存储为字符串):

  1. ​int (整型):​​ PlayerPrefs.SetInt(string key, int value);
  2. ​float (浮点型):​​ PlayerPrefs.SetFloat(string key, float value);
  3. ​string (字符串):​​ PlayerPrefs.SetString(string key, string value);

存储相关

PlayerPrefs.GetInt(\"myAge\", 18);PlayerPrefs.GetFloat(\"myFloat\", 177.8f);PlayerPrefs.GetString(\"myName\", \"DamnF\");//直接调用Set方法,只会把数据存储到内存中//当游戏结束时 Unity会自动把数据存到硬盘中//如果游戏不是正常结束 而是崩溃 数据是不会存到硬盘中的PlayerPrefs.Save();//只要调用该方法 就会马上存到硬盘中

PlayerPrefs具有局限性,只能存储三种类型数据,如果想存别的,只能降低精度 或上升精度来存储

存储bool类型:

bool sex = true;PlayerPrefs.GetInt(\"sex\", sex ? 1 : 0);

如果不同类型用同一键名进行存储 会进行覆盖

读取相关

 int age = PlayerPrefs.GetInt(\"myAge\"); float height = PlayerPrefs.GetFloat(\"myHeight\", 1000f); //如果找不到myHeight的值,会把第二个参数1000f作为默认值传入方法显示 string name = PlayerPrefs.GetString(\"myName\");

判读数据是否存在

if(PlayerPrefs .HasKey (\"myName\")){ print(\"存在对应的键值对数据\");}

删除数据相关

 //删除指定键值对 PlayerPrefs.DeleteKey(\"myAge\"); //删除所有键值对 PlayerPrefs.DeleteAll();

练习题

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 items; public void Save() { PlayerPrefs.SetString(\"name\", name); PlayerPrefs.SetInt(\"age\", age); PlayerPrefs.SetInt(\"atk\",atk); PlayerPrefs.SetInt(\"def\", def); //存储多少个装备 PlayerPrefs .SetInt (\"ItemNum\",items .Count); //存储每个装备 for (int i = 0; i < items .Count ; i++) { PlayerPrefs.SetInt(\"ItemID\" + i, items[i].id); PlayerPrefs.SetInt(\"ItemNum\" + i, items[i].num); } PlayerPrefs .Save (); } public void Load() { name= PlayerPrefs.GetString(\"name\",\"未命名\"); age= PlayerPrefs.GetInt(\"age\", 18); atk= PlayerPrefs.GetInt(\"atk\", 11); def= PlayerPrefs.GetInt(\"def\", 123); //得到多少个装备 int num = PlayerPrefs.GetInt(\"ItemNum\", 0); //初始化容器 items = new List(); Item item; for (int i = 0; i < num ; i++) { item = new Item(); item.id = PlayerPrefs.GetInt(\"ItemID\" + i); item.num = PlayerPrefs.GetInt(\"ItemNum\" + i); items .Add (item); } }}public class Lesson1_exericse : 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 = \"DamnF\"; //p.age = 21; //p.atk = 999; //p.def = 4444; //p.Save (); //p.Load (); //print(p.name); //print(p.age); //print(p.atk); //print(p.def); Player p = new Player(); p.Load(); //装备信息 print(p.items .Count ); for (int i = 0; i < p.items .Count ; i++) { print(\"道具Id\"+p.items[i].id); print(\"道具数量\"+p.items[i].num ); } Item item=new Item(); item.id = 1; item.num = 1; p.items .Add(item); Item item1 = new Item(); item1.id = 1; item1.num = 1; p.items.Add(item1); p.Save(); } // Update is called once per frame void Update() { }}

数据存储位置

windows

  • 位置 (Unity 2020.1 之前版本):​
    • 存储在一个 ​​注册表项​​ 中。
    • 具体路径HKEY_CURRENT_USER\\Software\\[CompanyName]\\[ProductName]
    • [CompanyName]:你在 Unity 项目设置 (Edit -> Project Settings -> Player -> Company Name) 或构建时设置的 \"Company Name\"。
    • [ProductName]:你在 Unity 项目设置 (Edit -> Project Settings -> Player -> Product Name) 或构建时设置的 \"Product Name\"。
  • ​位置 (Unity 2020.1 及之后版本):​
    • 出于兼容性、安全和跨平台一致性考虑,​​默认存储方式改为文件存储​​。
    • ​文件路径:​
      • %userprofile%\\AppData\\LocalLow\\[CompanyName]\\[ProductName]\\
      • 文件名通常是:PlayerPrefs.txt 或基于项目标识的文件。
    • %userprofile% 是当前用户的文件夹(例如 C:\\Users\\YourUsername)。
    • AppData\\LocalLow 文件夹是一个具有低完整性级别的特殊文件夹(适用于可能处理敏感数据的应用程序)。
  • ​如何访问:​
    • 打开文件资源管理器。
    • 在地址栏直接输入 %userprofile%\\AppData\\LocalLow\\[CompanyName],回车。
    • 查找你的游戏项目名称文件夹,里面的文件就是 PlayerPrefs 数据。
  • ​自定义路径 (Unity 2020.1+):​
    • 如果你在首次访问 PlayerPrefs 之前调用了 PlayerPrefs.SetFilePath(string fullPath),数据将存储在 fullPath 指定的完整路径文件中(例如 C:\\MyGameData\\my_prefs.dat)。

Android

  • ​位置:​
    • PlayerPrefs 使用 Android 的 ​​Shared Preferences​​ 机制进行存储。
    • 存储在应用私有目录下的一个 ​​XML 文件​​ 中。
    • ​完整路径 (在设备上):​
      /data/data/[package.name]/shared_prefs/unity.[player_settings_identifier].v2.playerprefs.xml
    • [package.name]:你的 Android 应用的唯一包名(例如 com.YourCompany.YourGame)。
    • [player_settings_identifier]:基于 Player Settings 计算出的一个标识符,通常和你的游戏项目名强相关,但不直接是项目名(可以简单理解为游戏唯一标识)。
  • ​文件内容:​
    • 是一个 XML 文件,键和值(字符串形式)清晰可见。
    • .v2. 表明使用的是 Unity 的 v2 偏好设置系统(较新的稳定版本)

Ios

   位置:​

  • PlayerPrefs 使用 iOS 的 ​​User Defaults 系统​​(NSUserDefaults API)进行存储。
  • 存储在应用沙盒内一个特定的 ​​Property List (.plist) 文件​​ 中。
  • ​完整路径 (在设备上):​
    /var/mobile/Containers/Data/Application/[App-GUID]/Library/Preferences/[bundle.id].plist
  • [App-GUID]:iOS 系统为每个已安装应用随机生成的唯一目录标识符(UDID)。每次应用重新安装都会变。
  • [bundle.id]:你的应用的 Bundle Identifier (在 Unity 的 Player Settings 中设置,类似于 Android 的包名,如 com.YourCompany.YourGame)。最终文件名通常就是 [bundle.id].plist

所有平台上的存储文件​​默认都没有加密​​,内容可视可修改(易被玩家作弊)。​​绝不用 PlayerPrefs 存需要保护的核心数据!

PlayerPrefs数据的唯一性

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

练习题--玩家游戏排行榜

using System.Collections;using System.Collections.Generic;using UnityEngine;public class RankInfoList{ public List rankLists; public void Add(string name,int score,int time) { rankLists .Add (new RankInfo (name,score,time)); } public RankInfoList () { Load(); } public void Save() { //设置rankLists中RankInfo的数量 PlayerPrefs .SetInt (\"RankInfoNum\",rankLists .Count); for (int i = 0; i < rankLists.Count; i++) { PlayerPrefs.SetString(\"rankName\" + i, rankLists[i].rankName); PlayerPrefs.SetInt(\"rankScore\" + i, rankLists[i].rankScore); PlayerPrefs.SetInt(\"rankTime\" + i, rankLists[i].rankTime); } PlayerPrefs .Save(); } private void Load() { //得到rankLists中RankInfo的数量 int num = PlayerPrefs.GetInt(\"RankInfoNum\", 0); //初始化容器 rankLists = new List(); RankInfo rankInfo; for (int i = 0;i < num;i++) { rankInfo = new RankInfo(PlayerPrefs.GetString(\"rankName\" + i),  PlayerPrefs.GetInt(\"rankScore\" + i),  PlayerPrefs.GetInt(\"rankTime\" + i)); rankLists.Add(rankInfo); } }}/// /// 单条玩家排行信息/// public class RankInfo{ public string rankName; public int rankScore; public int rankTime; public RankInfo(string name,int score,int time) { rankName = name; rankScore = score; rankTime = time; }}public class Lesson2 : MonoBehaviour{ // Start is called before the first frame update void Start() { RankInfoList rankList=new RankInfoList(); print(rankList.rankLists.Count); for (int i = 0; i < rankList .rankLists .Count ; i++) { print(\"名字:\" + rankList.rankLists[i].rankName); print(\"分数:\" + rankList.rankLists[i].rankScore); print(\"时间:\" + rankList.rankLists[i].rankTime); } rankList.Add(\"DamnF\", 100, 100); rankList.Save(); } // Update is called once per frame void Update() { }}