一、基础方法
1、介绍持久化
将内存中的数据存储到硬盘中。
2、PalyerPrefs是一个存储玩家数据的公共类。
3、存储相关
键是唯一的,即使是存储不同类型的。
4、读取相关
取值和其参数介绍:
第二个参数是用来赋予默认值的。并不会存储到硬盘中。
判断是否存在该键:
删除数据
练习题:
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;
using Unity.VisualScripting;
using UnityEngine;
public class Player
{
public string name1;
public int age;
public int atk;
public int def;
public List<Equip> equips;
public void SaveData()
{
PlayerPrefs.SetString("name", this.name1);
PlayerPrefs.SetInt("age", this.age);
PlayerPrefs.SetInt("atk", this.atk);
PlayerPrefs.SetInt("def", this.def);
PlayerPrefs.SetInt("equipsSum", equips.Count);
for (int i = 0; i < equips.Count; i++)
{
PlayerPrefs.SetInt($"equipId{i}", equips[i].id);
PlayerPrefs.SetInt($"equipNum{i}", equips[i].num);
}
PlayerPrefs.Save();
}
public void ReadData()
{
name1 = PlayerPrefs.GetString("name", "未知名称");
age = PlayerPrefs.GetInt("age", 20);
atk = PlayerPrefs.GetInt("atk", 1);
def = PlayerPrefs.GetInt("def", 1);
int sum = PlayerPrefs.GetInt("equipsSum", 0);
equips = new List<Equip>();
for(int i = 0; i < sum; i++)
{
Equip equip = new Equip();
equip.id = PlayerPrefs.GetInt($"equipId{i}", 0);
equip.num = PlayerPrefs.GetInt($"equipNum{i}", 0);
equips.Add(equip);
}
}
// 重写ToString方法以便更好地打印Player信息
public override string ToString()
{
return $"玩家{name1}({age}岁)目前攻击力:{atk},防御力:{def},拥有{equips.Count}种装备";
}
}
public class Player1 : MonoBehaviour
{
private void Start()
{
Player p1 = new Player();
p1.ReadData();
print(p1.ToString());
print(p1.equips.Count );
print($"7777玩家{p1.name1}({p1.age}岁)目前攻击力:{p1.atk},防御力:{p1.def}");
for (int i = 0; i < p1.equips.Count; i++)
{
print($"拥有装备{p1.equips[i].id}共{p1.equips[i].num}件");
}
p1.name1 = "战神";
p1.age = 88;
p1.def = 7;
p1.atk = 7;
Equip e1 = new Equip();
e1.id = 1;
e1.num = 1;
p1.equips.Add(e1);
p1.SaveData();
}
}
public class Equip
{
public int id;
public int num;
}
二、存储位置
1、不同平台位置:
windows:
Android:
IOS:
2、保证数据不重复
PlayerPrefs主要作用
三、反射复习
ISAssignableFrom用于判断调用者是否可以使用传入参数分配空间。 CreateInstance用于创建实例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class Fa
{
}
public class Son : Fa
{
}
public class P : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Type fa = typeof(Fa);
Type son = typeof(Son);
if (fa.IsAssignableFrom(son))
{
print("可以分配");
Fa fa1 = Activator.CreateInstance(son) as Fa;
print(fa1);
}
}
}
GetGenericArguments用于获取泛型类型
四、PlayerPrefs拓展练习
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;
using Unity.VisualScripting;
using UnityEngine;
public class Player
{
public string keyName;
public string name1;
public int age;
public int atk;
public int def;
public List<Equip> equips = new List<Equip>();
public Dictionary<string, string> skillExplain = new Dictionary<string, string>();
}
public class Equip
{
public int id;
public string equipName;
public Equip()
{
}
public Equip(int id, string equipName)
{
this.id = id;
this.equipName = equipName;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using static UnityEditor.LightingExplorerTableColumn;
public class PlayerPrefsData
{
//使用单例模式
private static PlayerPrefsData prefsData = new PlayerPrefsData();
public static PlayerPrefsData PrefsData { get { return prefsData; } }
private PlayerPrefsData()
{
}
//存储
public void Save(object data, string keyName)
{
Type dataType = data.GetType();
FieldInfo[] dataInfo = dataType.GetFields();
string saveKeyname = "";
foreach (FieldInfo fieldInfo in dataInfo)
{
saveKeyname = $"{keyName}_{dataType.Name}_{fieldInfo.FieldType.Name}_{fieldInfo.Name}";
SaveFunc(saveKeyname, fieldInfo.GetValue(data));
}
}
//存储方法:
private void SaveFunc(string keyName, object value)
{
Type type = value.GetType();
if (type == typeof(string))
{
PlayerPrefs.SetString($"{keyName}", value.ToString());
}
else if (type == typeof(int))
{
PlayerPrefs.SetInt($"{keyName}", (int)value);
}
else if (type == typeof(float))
{
PlayerPrefs.SetFloat($"{keyName}", (float)value);
}
//判断该类型是否是IList的子类,因为List继承了IList
else if (typeof(IList).IsAssignableFrom(type))
{
Debug.Log("打印List");
IList valueIList = value as IList;
int index = 0;
PlayerPrefs.SetInt(keyName, valueIList.Count);
foreach (object obj in valueIList)
{
SaveFunc(keyName + index, obj);
index++;
}
}
else if (typeof(IDictionary).IsAssignableFrom(type))
{
Debug.Log("打印Dictionary");
IDictionary valueIDictionary = value as IDictionary;
int index = 0;
PlayerPrefs.SetInt(keyName, valueIDictionary.Count);//存储长度方便读取
foreach (object key in valueIDictionary.Keys)
{
SaveFunc(keyName + index + "_Key", key);
SaveFunc(keyName + index + "_Value", valueIDictionary[key]);
index++;
}
}
else
{
Save(value, keyName);
}
Debug.Log($"{keyName}:{value}");
}
//读取
public object Load(string keyName, Type type)
{
FieldInfo[] fieldInfos = type.GetFields();
string loadKeyname = "";
object data = Activator.CreateInstance(type);
foreach (FieldInfo fieldInfo in fieldInfos)
{
loadKeyname = $"{keyName}_{type.Name}_{fieldInfo.FieldType.Name}_{fieldInfo.Name}";
fieldInfo.SetValue(data, LoadFunc(loadKeyname, fieldInfo.FieldType));
}
return data;
}
public object LoadFunc(string loadKeyname, Type fieldInfoType)
{
if (fieldInfoType == typeof(int))
{
return PlayerPrefs.GetInt(loadKeyname, -1);
}
else if (fieldInfoType == typeof(float))
{
return PlayerPrefs.GetFloat(loadKeyname, -1.0f);
}
else if (fieldInfoType == typeof(string))
{
return PlayerPrefs.GetString(loadKeyname, "未赋值");
}
else if (typeof(IList).IsAssignableFrom(fieldInfoType))
{
Debug.Log("读取List");
int count = PlayerPrefs.GetInt(loadKeyname, 0);
if (count == 0)
{
return null;
}
IList lists = Activator.CreateInstance(fieldInfoType) as IList;
for (int i = 0; i < count; i++)
{
lists.Add(LoadFunc(loadKeyname + i, fieldInfoType.GetGenericArguments()[0]));
}
return lists;
}
else if (typeof(IDictionary).IsAssignableFrom(fieldInfoType))
{
Debug.Log("读取Dictionary");
int count = PlayerPrefs.GetInt(loadKeyname, 0);
if (count == 0)
{
return null;
}
IDictionary dictionary = Activator.CreateInstance(fieldInfoType) as IDictionary;
for (int i = 0; i < count; i++)
{
dictionary.Add(LoadFunc(loadKeyname + i + "_Key", fieldInfoType.GetGenericArguments()[0]), LoadFunc(loadKeyname + i + "_Value", fieldInfoType.GetGenericArguments()[1]));
}
return dictionary;
}
else
{
return Load(loadKeyname, fieldInfoType);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class P : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
//Player player = new Player();
//player.keyName = "player1";
//player.name1 = "阿龙";
//player.age = 20;
//player.atk = 10;
//player.def = 2;
//List<Equip> equipList = new List<Equip> { new Equip(1, "木剑"), new Equip(2, "铁斧") };
//player.skillExplain = new Dictionary<string, string> { { "半月斩", "弧线的一次斩击" }, {"鞑靼牛肉", "你可以使用生牛肉"} };
//player.equips.AddRange(equipList);
//PlayerPrefsData.PrefsData.Save(player, player.keyName);
Player player1 = PlayerPrefsData.PrefsData.Load("player1", typeof(Player)) as Player;
}
private void Update()
{
}
}