经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 软件/图像 » unity » 查看文章
Unity学习笔记--数据持久化之PlayerPrefs的使用
来源:cnblogs  作者:畅知  时间:2023/11/20 8:56:31  对本文有异议

数据持久化

PlayerPrefs相关

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

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

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

PC端: PlayerPrefs 存储在 HKCU\Software[公司名称][产品名称] 项下的注册表中
其中公司和产品名称是 在“Project Settings”中设置的名称。

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

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

优点:使用简单

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

PlayerPrefs存储工具类:

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

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

  1. using System;
  2. using System.Collections;
  3. using System.Reflection;
  4. using UnityEngine;
  5. namespace Framwork
  6. {
  7. /// <summary>
  8. /// Playerprefs 存储类
  9. /// </summary>
  10. public class PlayerPrefsManager
  11. {
  12. private static PlayerPrefsManager instance=new PlayerPrefsManager();
  13. public static PlayerPrefsManager Instance => instance;
  14. private PlayerPrefsManager()
  15. {
  16. }
  17. /// <summary>
  18. /// 存取数据的方法
  19. /// </summary>
  20. /// <param name="obj">数据实体</param>
  21. /// <param name="name">数据名称</param>
  22. public void SaveData(object data, string keyName)
  23. {
  24. Type type = data.GetType();
  25. FieldInfo[] infos = type.GetFields();
  26. string tempKey="null";
  27. FieldInfo tempInfo = null;
  28. for (int i = 0; i < infos.Length; i++)
  29. {
  30. //获取数据数据类型
  31. tempInfo = infos[i];
  32. Debug.Log("Types==="+tempInfo);
  33. //类的名字+类的类型 + 数据内容名字+数据类型
  34. //作为存储的keyName键
  35. tempKey = keyName + "_" + type.Name + "_" + tempInfo.Name
  36. + "_" + tempInfo.FieldType.Name;
  37. SaveValue(tempInfo.GetValue(data),tempKey);
  38. }
  39. //进行值的获取
  40. //tempInfo.GetValue(data);
  41. PlayerPrefs.Save();
  42. }
  43. /// <summary>
  44. /// 读取数据的类型
  45. /// </summary>
  46. /// <param name="type">要读取的数据类型</param>
  47. /// <param name="name">要读取的数据名称</param>
  48. /// <returns>返回数据实体</returns>
  49. public object LoadData(Type type, string name)
  50. {
  51. //获取数据中的类型
  52. FieldInfo[] infos = type.GetFields();
  53. //创建存储数据信息的实体
  54. object data = Activator.CreateInstance(type);
  55. string tempName = null;
  56. FieldInfo tempInfo = null;
  57. for (int i = 0; i < infos.Length; i++)
  58. {
  59. tempInfo = infos[i];//数据结构中的数据名称
  60. tempName = name + "_" + type.Name + "_" +tempInfo.Name+"_"
  61. +tempInfo.FieldType.Name;//数据结构中的数据名称类型
  62. //装载的容器 容器中的数据
  63. //进行数据装载
  64. tempInfo.SetValue(data,LoadValue(tempInfo.FieldType,tempName));
  65. }
  66. return data;
  67. }
  68. /// <summary>
  69. /// 进行具体的类型数据的存储
  70. /// </summary>
  71. /// <param name="data"></param>
  72. /// <param name="keyName"></param>
  73. private void SaveValue(object value, string keyName)
  74. {
  75. Type fieldType = value.GetType();
  76. if (fieldType == typeof(int))
  77. {
  78. Debug.Log("存储int"+value);
  79. PlayerPrefs.SetInt(keyName,(int)value);
  80. }else if (fieldType == typeof(float))
  81. {
  82. Debug.Log("存储float"+value);
  83. PlayerPrefs.SetFloat(keyName,(float)value);
  84. }else if (fieldType == typeof(string))
  85. {
  86. Debug.Log("存储string"+value);
  87. PlayerPrefs.SetString(keyName,value.ToString());
  88. }
  89. //对于List存储的设置
  90. //根据存储的字段类型和IList是否是父子关系
  91. else if(typeof(IList).IsAssignableFrom(fieldType))
  92. {
  93. //父类装子类
  94. IList list=value as IList;
  95. //存储元素数量
  96. PlayerPrefs.SetInt(keyName,list.Count);
  97. Debug.Log("存储List长度为"+list.Count);
  98. int index = 0;
  99. foreach (var obj in list)
  100. {
  101. //存储list列表中元素内容
  102. //命名形式是 list名字+索引编号
  103. //递归调用存储
  104. SaveValue(obj,keyName+index);
  105. index++;
  106. }
  107. }else if (typeof(IDictionary).IsAssignableFrom(fieldType))
  108. {
  109. IDictionary dictionary = value as IDictionary;
  110. //存储数据个数
  111. PlayerPrefs.SetInt(keyName,dictionary.Count);
  112. Debug.Log("存储Dic长度为"+dictionary.Count);
  113. int index = 0;
  114. foreach (var key in dictionary.Keys)
  115. {
  116. //存储键
  117. SaveValue(key,keyName+"_key_"+index);
  118. //存储值
  119. SaveValue(dictionary[key],keyName+"_value_"+index);
  120. index++;
  121. }
  122. }//自定义数据类型的存储 进行解析
  123. else
  124. {
  125. SaveData(value,keyName);
  126. }
  127. }
  128. private object LoadValue(Type type, string name)
  129. {
  130. if (type == typeof(int))
  131. {
  132. return PlayerPrefs.GetInt(name,0);
  133. }else if (type == typeof(float))
  134. {
  135. return PlayerPrefs.GetFloat(name,0.0f);
  136. }else if (type == typeof(string))
  137. {
  138. return PlayerPrefs.GetString(name,"");
  139. }else if (typeof(IList).IsAssignableFrom(type))
  140. {
  141. //读取列表
  142. int count = PlayerPrefs.GetInt(name);
  143. IList tempList=Activator.CreateInstance(type) as IList;
  144. for (int i = 0; i < count; i++)
  145. {
  146. //获取List中存储元素的类型 type.GetGenericArguments()[0]
  147. tempList.Add(LoadValue(type.GetGenericArguments()[0],name+i));
  148. }
  149. return tempList;
  150. }else if (typeof(IDictionary).IsAssignableFrom(type))
  151. {
  152. //进行对字典的读取
  153. int count = PlayerPrefs.GetInt(name);
  154. IDictionary tempDictionary=Activator.CreateInstance(type) as IDictionary;
  155. for (int i = 0; i < count; i++)
  156. {
  157. tempDictionary.Add(LoadValue(type.GetGenericArguments()[0], name + "_key_" + i),
  158. LoadValue(type.GetGenericArguments()[1], name + "_value_" + i));
  159. }
  160. return tempDictionary;
  161. }
  162. else
  163. {
  164. //读取自定义类成员的设置
  165. return LoadData(type, name);
  166. }
  167. }
  168. }
  169. }

附:

测试脚本

  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. namespace Framwork
  4. {
  5. //注意:
  6. //1 自定义数据结构类型中要有有效的无参构造函数
  7. public class PlayerInfo
  8. {
  9. public int age;
  10. public string name;
  11. public float height;
  12. public int sex;//0是女 1是男
  13. public ItemInfo ItemInfo;
  14. //list存储测试
  15. public List<int> list;
  16. public Dictionary<int, string> dic;
  17. }
  18. public class ItemInfo
  19. {
  20. public int stu_no;//学号
  21. public int stu_class;//班级
  22. public ItemInfo()
  23. {
  24. }
  25. public ItemInfo(int no,int classNo)
  26. {
  27. stu_no = no;
  28. stu_class = classNo;
  29. }
  30. }
  31. /// <summary>
  32. /// 测试类
  33. /// </summary>
  34. public class TestPlayerPrefsTest:MonoBehaviour
  35. {
  36. private PlayerInfo playerInfo;
  37. private PlayerInfo playerInfo1;
  38. private void Start()
  39. {
  40. //读取数据
  41. playerInfo = new PlayerInfo();
  42. // Type fieldType = playerInfo.GetType();
  43. playerInfo.age = 18;
  44. playerInfo.name = "TonyChang";
  45. playerInfo.height = 175.8f;
  46. playerInfo.sex = 1;
  47. playerInfo.ItemInfo = new ItemInfo(2001, 2);
  48. playerInfo.list = new List<int>(){1,5,6,8};
  49. playerInfo.dic = new Dictionary<int, string>();
  50. playerInfo.dic.Add(1,"Tony");
  51. playerInfo.dic.Add(2,"Jeny");
  52. playerInfo.dic.Add(3,"JayChou");
  53. //进行数据保存
  54. PlayerPrefsManager.Instance.SaveData(playerInfo,"Player1");
  55. playerInfo1 = PlayerPrefsManager.Instance.LoadData(typeof(PlayerInfo), "Player1") as PlayerInfo;
  56. Debug.Log("age=="+playerInfo1.age);
  57. Debug.Log("name=="+playerInfo1.name);
  58. Debug.Log("sex=="+playerInfo1.sex);
  59. Debug.Log("List[1]=="+playerInfo1.list[1]);
  60. Debug.Log("Dic[1]=="+playerInfo1.dic[1]);
  61. }
  62. }
  63. }

原文链接:https://www.cnblogs.com/TonyCode/p/17842598.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号