本模型支持int、string、float、字典、list等类型及封装类的存取。(已实测)
在测试的时候,发现一旦在类中声明了list的变量成员,用playerprefs可以存储,但是读取的时候,列表中第二个值会有问题,因此对int类型的存取整体改为了强转为string进行存取。
有什么问题可以评论,我会回复。
另外,引入几个知识点:
- typeof(IList).IsAssignableFrom(type) 用来判断IList是否为type的基类
- type.GetGenericArguments()[0] 获取type类的所有参数的类型,0代表第一个参数
- IList是所有List的基类,IDictionary是所有Dictionary的基类。
以下是具体代码:
using System;
using System.Collections;
using System.Reflection;
using UnityEngine;
public class SaveMyData
{
//建立一个Instance
private static SaveMyData instance = new SaveMyData();
public static SaveMyData Instance
{
get
{
return instance;
}
}
private SaveMyData()
{
}
//存储数据值
public void SaveValue(object value, string keyName)
{
Type valueType = value.GetType();
//int类型存储
if (valueType == typeof(int))
{
//转换为string存储(正常按int存储时,类结构下的list会有数据读取错误-估计是unity的bug)
int v =(int)value;
PlayerPrefs.SetString(keyName+"tostr", v.ToString());
// //正常int存储
// PlayerPrefs.SetInt(keyName, v);
}
//float类型存储
else if (valueType == typeof(float))
{
PlayerPrefs.SetFloat(keyName, (float)value);
}
//string类型存储
else if (valueType == typeof(string))
{
PlayerPrefs.SetString(keyName, (string)value);
}
//bool类型存储,转为Int类型
else if (valueType == typeof(bool))
{
PlayerPrefs.SetInt(keyName, (bool)value ? 1 : 0);
}
//List列表存储
else if (typeof(IList).IsAssignableFrom(valueType))
{
IList list = value as IList;
//先存储数量
PlayerPrefs.SetInt(keyName, list.Count);
//再存储子项
for (int i = 0; i < list.Count; i++)
{
SaveValue(list[i], keyName + i);
}
}
//Dictionary字典存储
else if (typeof(IDictionary).IsAssignableFrom(valueType))
{
IDictionary dic = value as IDictionary;
//先存储数量
PlayerPrefs.SetInt(keyName, dic.Count);
//再存储子项
int i = 0;
foreach (var item in dic.Keys)
{
SaveValue(item, keyName + "_key_" + i);
SaveValue(dic[item], keyName + "_value_" + i);
i++;
}
}
//自定义类型,需换取成员变量
else
{
//获取Type
Type dataType = value.GetType();
//获取成员变量
FieldInfo[] fields = dataType.GetFields();
//存储数据,命名规则:keyName_数据类型_字段类型_字段名
foreach (var item in fields)
{
// string name = keyName + "_" + dataType.Name + "_" + item.FieldType.Name + "_" + item.Name;
string name = keyName + "_" + item.Name;
SaveValue(item.GetValue(value), name);
}
}
//同步数据
PlayerPrefs.Save();
}
//读取数据值
public object LoadValue(Type type , string keyName)
{
//获取int
if (type == typeof(int))
{
//转换存储的string-获取int
string v = PlayerPrefs.GetString(keyName+"tostr", "0");
return Convert.ToInt32(v);
//正常获取int
// return PlayerPrefs.GetInt(keyName, 0);
}
//获取float
else if (type == typeof(float))
{
return PlayerPrefs.GetFloat(keyName, 0);
}
//获取string
else if (type == typeof(string))
{
return PlayerPrefs.GetString(keyName, "");
}
//获取bool
else if (type == typeof(bool))
{
return PlayerPrefs.GetInt(keyName, 0) == 1;
}
//获取List
else if (typeof(IList).IsAssignableFrom(type))
{
//获取长度
int count = PlayerPrefs.GetInt(keyName, 0);
// //实例化list
IList list = Activator.CreateInstance(type) as IList;
for (int i = 0; i < count; i++)
{
//获取对应的子项数据,放入列表
list.Add(LoadValue(type.GetGenericArguments()[0], keyName + i));
}
return list;
}
//获取Dictinary字典
else if (typeof(IDictionary).IsAssignableFrom(type))
{
//获取长度
int count = PlayerPrefs.GetInt(keyName, 0);
//实例化Dictionary
IDictionary dic = Activator.CreateInstance(type) as IDictionary;
for (int i = 0; i < count; i++)
{
//获取对应的子项
dic.Add(LoadValue(type.GetGenericArguments()[0], keyName + "_key_" + i), LoadValue(type.GetGenericArguments()[1], keyName + "_value_" + i));
}
return dic;
}
//获取其他类型
else
{
//实例化对象
object data = Activator.CreateInstance(type);
//获取成员变量
FieldInfo[] fields = type.GetFields();
//根据成员变量获取对应名称,keyname_类名_成员类型_成员名
for (int i = 0; i < fields.Length; i++)
{
FieldInfo info = fields[i];
// string name = keyName + "_" + type.Name + "_" + info.FieldType.Name + "_" + info.Name;
string name = keyName + "_" + info.Name;
//读取数据,设置给data对象
info.SetValue(data, LoadValue(info.FieldType, name));
}
return data;
}
}
}
如果你也在学习unity,请关注及点赞,关注和点赞越多,更新越多。