Unity学习笔记–数据持久化之PlayerPrefs的使用

  • Unity学习笔记–数据持久化之PlayerPrefs的使用已关闭评论
  • 89 次浏览
  • A+
所属分类:.NET技术
摘要

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


数据持久化

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 存储在 HKCUSoftware[公司名称][产品名称] 项下的注册表中
其中公司和产品名称是 在“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]);         }     } }