數(shù)據(jù)持久化
PlayerPrefs相關(guān)
PlayerPrefs是Unity游戲引擎中的一個類,用于在游戲中存儲和訪問玩家的偏好設(shè)置和數(shù)據(jù)。它可以用來保存玩家的游戲進(jìn)度、設(shè)置選項、最高分?jǐn)?shù)等信息。PlayerPrefs將數(shù)據(jù)存儲在本地文件中,因此可以在游戲重新啟動時保持?jǐn)?shù)據(jù)的持久性。
//PlayerPrefs的數(shù)據(jù)存儲 類似于鍵值對存儲 一個鍵對應(yīng)一個值
//提供了存儲3種數(shù)據(jù)的方法 int float string
//鍵: string類型
//值:int float string 對應(yīng)3種API
PlayerPrefs.SetInt("myAge", 18);
PlayerPrefs.SetFloat("myHeight", 177.5f);
PlayerPrefs.SetString("myName", "TonyChang");
//直接調(diào)用Set相關(guān)方法 只會把數(shù)據(jù)存到內(nèi)存里
//當(dāng)游戲結(jié)束時 Unity會自動把數(shù)據(jù)存到硬盤中
//如果游戲不是正常結(jié)束的 而是崩潰 數(shù)據(jù)是不會存到硬盤中的
//只要調(diào)用該方法 就會馬上存儲到硬盤中
PlayerPrefs.Save();
//PlayerPrefs是有局限性的 它只能存3種類型的數(shù)據(jù)
//如果你想要存儲別的類型的數(shù)據(jù) 只能降低精度 或者上升精度來進(jìn)行存儲
bool sex = true;
PlayerPrefs.SetInt("sex", sex ? 1 : 0);
//如果不同類型用同一鍵名進(jìn)行存儲 會進(jìn)行覆蓋
PlayerPrefs.SetFloat("myAge", 20.2f);
//注意 運(yùn)行時 只要你Set了對應(yīng)鍵值對
//即使你沒有馬上存儲Save在本地
//也能夠讀取出信息
//int
int age = PlayerPrefs.GetInt("myAge");
print(age);
//前提是 如果找不到myAge對應(yīng)的值 就會返回函數(shù)的第二個參數(shù) 默認(rèn)值
age = PlayerPrefs.GetInt("myAge", 100);
print(age);
//float
float height = PlayerPrefs.GetFloat("myHeight", 1000f);
print(height);
//string
string name = PlayerPrefs.GetString("myName");
print(name);
//第二個參數(shù) 默認(rèn)值 對于我們的作用
//就是 在得到?jīng)]有的數(shù)據(jù)的時候 就可以用它來進(jìn)行基礎(chǔ)數(shù)據(jù)的初始化
//判斷數(shù)據(jù)是否存在
if( PlayerPrefs.HasKey("myName") )
{
print("存在myName對應(yīng)的鍵值對數(shù)據(jù)");
}
//刪除指定鍵值對
PlayerPrefs.DeleteKey("myAge");
//刪除所有存儲的信息
PlayerPrefs.DeleteAll();
PlayerPrefs中存儲的數(shù)據(jù)存儲在哪里?
PC端: PlayerPrefs 存儲在 HKCU\Software[公司名稱][產(chǎn)品名稱] 項下的注冊表中
其中公司和產(chǎn)品名稱是 在“Project Settings”中設(shè)置的名稱。
安卓: /data/data/包名/shared_prefs/pkg-name.xml
PlayerPrefs中數(shù)據(jù)的唯一性,PlayerPrefs中數(shù)據(jù)的唯一性是由key決定的,不同的key決定了不同的數(shù)據(jù),同一個項目中如果不同數(shù)據(jù)key相同會造成數(shù)據(jù)丟失,要保證數(shù)據(jù)名稱命名的唯一性規(guī)則。
優(yōu)點(diǎn):使用簡單
缺點(diǎn):存儲數(shù)據(jù)類型有限、安全性差(直接找到在設(shè)備上的存儲的位置查看設(shè)置)
PlayerPrefs存儲工具類:
為了方便進(jìn)行數(shù)據(jù)的存儲,使用PlayerPrefs中進(jìn)行存儲方法的設(shè)置的存??!
主要實(shí)現(xiàn)功能是數(shù)據(jù)的讀和數(shù)據(jù)的取~ 通過反射進(jìn)行數(shù)據(jù)類型的獲取,利用PlayerPrefs進(jìn)行數(shù)據(jù)存儲。
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>
/// 存取數(shù)據(jù)的方法
/// </summary>
/// <param name="obj">數(shù)據(jù)實(shí)體</param>
/// <param name="name">數(shù)據(jù)名稱</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++)
{
//獲取數(shù)據(jù)數(shù)據(jù)類型
tempInfo = infos[i];
Debug.Log("Types==="+tempInfo);
//類的名字+類的類型 + 數(shù)據(jù)內(nèi)容名字+數(shù)據(jù)類型
//作為存儲的keyName鍵
tempKey = keyName + "_" + type.Name + "_" + tempInfo.Name
+ "_" + tempInfo.FieldType.Name;
SaveValue(tempInfo.GetValue(data),tempKey);
}
//進(jìn)行值的獲取
//tempInfo.GetValue(data);
PlayerPrefs.Save();
}
/// <summary>
/// 讀取數(shù)據(jù)的類型
/// </summary>
/// <param name="type">要讀取的數(shù)據(jù)類型</param>
/// <param name="name">要讀取的數(shù)據(jù)名稱</param>
/// <returns>返回數(shù)據(jù)實(shí)體</returns>
public object LoadData(Type type, string name)
{
//獲取數(shù)據(jù)中的類型
FieldInfo[] infos = type.GetFields();
//創(chuàng)建存儲數(shù)據(jù)信息的實(shí)體
object data = Activator.CreateInstance(type);
string tempName = null;
FieldInfo tempInfo = null;
for (int i = 0; i < infos.Length; i++)
{
tempInfo = infos[i];//數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)名稱
tempName = name + "_" + type.Name + "_" +tempInfo.Name+"_"
+tempInfo.FieldType.Name;//數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)名稱類型
//裝載的容器 容器中的數(shù)據(jù)
//進(jìn)行數(shù)據(jù)裝載
tempInfo.SetValue(data,LoadValue(tempInfo.FieldType,tempName));
}
return data;
}
/// <summary>
/// 進(jìn)行具體的類型數(shù)據(jù)的存儲
/// </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存儲的設(shè)置
//根據(jù)存儲的字段類型和IList是否是父子關(guān)系
else if(typeof(IList).IsAssignableFrom(fieldType))
{
//父類裝子類
IList list=value as IList;
//存儲元素數(shù)量
PlayerPrefs.SetInt(keyName,list.Count);
Debug.Log("存儲List長度為"+list.Count);
int index = 0;
foreach (var obj in list)
{
//存儲list列表中元素內(nèi)容
//命名形式是 list名字+索引編號
//遞歸調(diào)用存儲
SaveValue(obj,keyName+index);
index++;
}
}else if (typeof(IDictionary).IsAssignableFrom(fieldType))
{
IDictionary dictionary = value as IDictionary;
//存儲數(shù)據(jù)個數(shù)
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++;
}
}//自定義數(shù)據(jù)類型的存儲 進(jìn)行解析
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))
{
//進(jìn)行對字典的讀取
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
{
//讀取自定義類成員的設(shè)置
return LoadData(type, name);
}
}
}
}
附:文章來源:http://www.zghlxwxcb.cn/news/detail-746807.html
測試腳本文章來源地址http://www.zghlxwxcb.cn/news/detail-746807.html
using System.Collections.Generic;
using UnityEngine;
namespace Framwork
{
//注意:
//1 自定義數(shù)據(jù)結(jié)構(gòu)類型中要有有效的無參構(gòu)造函數(shù)
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;//學(xué)號
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()
{
//讀取數(shù)據(jù)
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");
//進(jìn)行數(shù)據(jù)保存
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]);
}
}
}
到了這里,關(guān)于Unity學(xué)習(xí)筆記--數(shù)據(jù)持久化之PlayerPrefs的使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!