太原cms建站模板,泰安网站建设工作室,建筑网站 法人签字,wordpress视频播放卡这里写目录标题 PlayerPrefs概述基本方法PlayerPrefs存储位置实践小项目反射知识补充数据管理类的创建反射存储数据----常用成员反射存储数据----List成员反射存储数据----Dictionary成员反射存储数据----自定义类成员反射读取数据----常用成员反射读取数据----List成员反射读取… 这里写目录标题 PlayerPrefs概述基本方法PlayerPrefs存储位置实践小项目反射知识补充数据管理类的创建反射存储数据----常用成员反射存储数据----List成员反射存储数据----Dictionary成员反射存储数据----自定义类成员反射读取数据----常用成员反射读取数据----List成员反射读取数据----Dic成员反射读取数据----自定义类成员加密思路生成资源包 PlayerPrefs概述
什么是数据持久化 数据持久化就是将内存中的数据模型转换为存储模型以及将存储模型转换为内存中的数据模型的统称。即将游戏数据存储到硬盘硬盘中数据读取到游戏中也就是传统意义上的存盘。
基本方法
PlayerPrefs是什么 是Unity提供的可以用于存储读取玩家数据的公共类 存储相关 PlayerPrefs的数据存储类似于键值对存储一个键对应一个值。 提供了存储3中数据的方法int、float、string 键string类型 值int float string对应3种API
PlayerPrefs.SetInt(myAge,18);
PlayerPrefs.SetString(myHeight,177f);
PlayerPrefs.SetString(myName,123);直接调用Set相关方法只会把数据存到内存里。当游戏结束时Unity会自动把数据存到硬盘中。如果游戏不是正常结束的而是崩溃数据是不会存到硬盘中的。
只要调用该方法就会马上存储到硬盘中。
PlayerPrefs.Save();PlayerPrefs是有局限性的它只能存3种类型的数据如果想要存储别的类型的数据只能降低精度或者上升精度来进行存储。
如果不同类型用同一键名进行存储会进行覆盖。
PlayerPrefs.SetFloat(myAge,20.2f);读取相关 运行时只要使用了Set相关方法设置了对应键值对即使没有马上存储在Save在本地也可以读取出信息。
//int
int age PlayerPrefs.GetInt(myAge);
age PlayerPrefs.GetInt(myAge,100);
//float
float height PlayerPrefs.GetFloat(myHeight,1000f);
//string
string name PlayerPrefs.GetString(myName);第二个参数默认值的作用就是在得到没有的数据的时候就可以用它来进行基础数据的初始化。
判断数据是否存在。
if(PlayerPrefs.HasKey(myName))
{
}删除数据 删除指定键值对
PlayerPrefs.DeleteKey(myAge);删除所有存储的信息
PlayerPrefs.DeleteAll();PlayerPrefs存储位置
PlayerPrefs存储的数据存在哪里 1、Windows PlayerPrefs存储在HKCU\Software\[公司名称]\[产品名称]项下的注册表中 其中公司和产品名称是在“Project Settings”中设置的名称
查找过程 运行regedit HKEY_CURRENT_USER SOFTWARE Unity UnityEditor 公司名称 产品名称 2、Android /data/data/包名/shared_prefs/pkg-name.xml 3、IOS /Library/Preferences/[应用ID].plist PlayerPrefs数据唯一性 PlayerPrefs中不同数据的唯一性是由key决定的不同的key决定了不同的数据。同一项目中如果不同数据key相同会造成数据丢失。要保证数据不丢失就要建立一个保证key唯一的规则。
实践小项目
反射知识补充
反射相关内容请移步C#进阶学习 反射知识回顾 反射3剑客 1、Type用于获取类的所有信息、字段、属性、方法等等。 2、Assembly用于获取程序集通过程序集获取Type。 3、Activator用于快速实例化对象。 判断一个类型的对象是否可以让另一个类型为自己分配空间父类装子类
public class Father
{
}
public class Son:Father
{
}
Type fatherType typeof(Father);
Type sonType typeof(Son);
//判断是否可以通过传入的类型为自己分配空间
if(fatherType.IsAssignableFrom(sonType))
{
}通过反射获取泛型类型
Liststring list new Liststring();
Type listType list.GetType();
Type[] types listType.GetGenericArguments();//获取到泛型类型stringDictionarystring,float dic new Dictionarystring,float();
Type dicType dic.GetType();
types dicType.GetGenericArguments();数据管理类的创建
//PlayerPrefs数据管理类统一管理数据的存储和读取
public class PlayerPrefsDataMgr
{private static PlayerPrefsDataMgr instance new PlayerPrefsDataMgr();public static PlayerPrefsDataMgr Instance{get{return instance;}}private PlayerPrefsDataMgr(){}//私有构造//存储数据public void SaveData(object data,string keyName){}//读取数据public object LoadData(Type type,string keyName){return null;}
}反射存储数据----常用成员
//存储数据
//通过Type得到传入数据对象的所有的字段然后结合PlayerPrefs来进行存储
public void SaveData(object data,string keyName)
{//获取传入数据对象的所有字段Type dataType data.GetType(); FieldInfo[] infos dataTypes.GetFields();//自己定义一个key规则进行数据存储//keyName_数据类型_字段类型_字段名//遍历这些字段进行数据存储string saveKeyName ;FieldInfo info;for(int i 0;i infos.Length;i){//字段的类型info.FieldType.Name//字段的名字info.Nameinfo infos[i];//得到具体的字段信息saveKeyName keyName _ dataType.Name _ info.FieldType.Name _ info.Name;//封装一个方法进行存储//获取值info.GetValue(data)SaveValue(info.GetValue(data),saveKeyName);}
}
private void SaveValue(object value,string keyName)
{//PlayerPrefs只支持3种类型存储//判断数据类型是什么类型然后调用具体的方法来存储Type fieldType value.GetType();if(fieldType typeof(int)){PlayerPrefs.SetInt(keyName,(int)value);}else if(fieldType typeof(float)){PlayerPrefs.SetFloat(keyName,(float)value);}else if(fieldType typeof(string)){PlayerPrefs.SetString(keyName,value.ToString());}else if(fieldType typeof(bool)){PlayerPrefs.SetInt(keyName,(bool)value ? 1 : 0);}
}反射存储数据----List成员
private void SaveValue(object value,string keyName)
{//PlayerPrefs只支持3种类型存储//判断数据类型是什么类型然后调用具体的方法来存储Type fieldType value.GetType();if(fieldType typeof(int)){PlayerPrefs.SetInt(keyName,(int)value);}else if(fieldType typeof(float)){PlayerPrefs.SetFloat(keyName,(float)value);}else if(fieldType typeof(string)){PlayerPrefs.SetString(keyName,value.ToString());}else if(fieldType typeof(bool)){PlayerPrefs.SetInt(keyName,(bool)value ? 1 : 0);}//判断字段是不是IList的子类else if(typeof(IList).IsAssignableFrom(fieldType)){//父类装子类IList list value as IList;//先存储数量PlayerPrefs.SetInt(keyName,list.Count);//存储具体的值int index 0;foreach(object obj in list){SaveValue(obj,keyName index);index;}反射存储数据----Dictionary成员
private void SaveValue(object value,string keyName)
{//PlayerPrefs只支持3种类型存储//判断数据类型是什么类型然后调用具体的方法来存储Type fieldType value.GetType();if(fieldType typeof(int)){PlayerPrefs.SetInt(keyName,(int)value);}else if(fieldType typeof(float)){PlayerPrefs.SetFloat(keyName,(float)value);}else if(fieldType typeof(string)){PlayerPrefs.SetString(keyName,value.ToString());}else if(fieldType typeof(bool)){PlayerPrefs.SetInt(keyName,(bool)value ? 1 : 0);}//判断字段是不是IList的子类else if(typeof(IList).IsAssignableFrom(fieldType)){//父类装子类IList list value as IList;//先存储数量PlayerPrefs.SetInt(keyName,list.Count);//存储具体的值int index 0;foreach(object obj in list){SaveValue(obj,keyName index);index;}else if(typeof(IDictionary).IsAssignableFrom(fieldType)){IDictionary dic value as IDictionary;//存字典长度PlayerPrefs.SetInt(keyName,dic.Count);//遍历存储Dic里面的具体值int index 0;foreach(object key in dic){SaveValue(key,keyName _key_ index);SaveValue(dic[key],keyName _value_ index);index;}}反射存储数据----自定义类成员
private void SaveValue(object value,string keyName)
{//PlayerPrefs只支持3种类型存储//判断数据类型是什么类型然后调用具体的方法来存储Type fieldType value.GetType();if(fieldType typeof(int)){PlayerPrefs.SetInt(keyName,(int)value);}else if(fieldType typeof(float)){PlayerPrefs.SetFloat(keyName,(float)value);}else if(fieldType typeof(string)){PlayerPrefs.SetString(keyName,value.ToString());}else if(fieldType typeof(bool)){PlayerPrefs.SetInt(keyName,(bool)value ? 1 : 0);}//判断字段是不是IList的子类else if(typeof(IList).IsAssignableFrom(fieldType)){//父类装子类IList list value as IList;//先存储数量PlayerPrefs.SetInt(keyName,list.Count);//存储具体的值int index 0;foreach(object obj in list){SaveValue(obj,keyName index);index;}else if(typeof(IDictionary).IsAssignableFrom(fieldType)){IDictionary dic value as IDictionary;//存字典长度PlayerPrefs.SetInt(keyName,dic.Count);//遍历存储Dic里面的具体值int index 0;foreach(object key in dic){SaveValue(key,keyName _key_ index);SaveValue(dic[key],keyName _value_ index);index;}}else{SaveData(value,keyName);}反射读取数据----常用成员
public object LoadData(Type type,string keyName)
{//根据你传入的Type创建一个对象用于存储数据object data Activator.CreateInstance(type);//得到所有字段FieldInfo[] infos type.GetFields();//用于拼接key的字符串string loadKeyName ;//用于存储单个字段信息的对象FieldInfo info;for(int i 0;i infos.Length;i){info infos[i];//key的拼接规则一定是和存储时一模一样这样才能找到对应数据loadKeyName keyName _ type.Name _ info.FieldType.Name _ info.Name;//有key就可以结合PlayerPrefs来读取数据info.SetValue(data,LoadValue(info.FieldType,loadKeyName));}return data;
}
private object LoadValue(Type fieldType,string keyName)
{//根据字段类型判断用哪个API读取if(fieldType typeof(int)){return PlayerPrefs.GetInt(keyName,0);}else if(fieldType typeof(float)){return PlayerPrefs.GetFloat(keyName,0);}else if(fieldType typeof(string)){return PlayerPrefs.GetString(keyName,);}else if(fieldType typeof(bool)){//自定义存储bool值规则return PlayerPrefs.GetInt(keyName,0) 1 ? true : false;}return null;
}反射读取数据----List成员
private object LoadValue(Type fieldType,string keyName)
{//根据字段类型判断用哪个API读取if(fieldType typeof(int)){return PlayerPrefs.GetInt(keyName,0);}else if(fieldType typeof(float)){return PlayerPrefs.GetFloat(keyName,0);}else if(fieldType typeof(string)){return PlayerPrefs.GetString(keyName,);}else if(fieldType typeof(bool)){//自定义存储bool值规则return PlayerPrefs.GetInt(keyName,0) 1 ? true : false;}else if(typeof(IList).IsAssignableFrom(fieldType)){//得到长度int count PlayerPrefs.GetInt(keyName,0);//实例化一个List对象进行赋值IList list Activator.CreateInstance(fieldType) as IList;for(int i 0;i count;i){//得到List中泛型的类型list.Add(LoadValue(fieldType.GetGenericArguments()[0],keyName i));}return list;}return null;
}反射读取数据----Dic成员
private object LoadValue(Type fieldType,string keyName)
{//根据字段类型判断用哪个API读取if(fieldType typeof(int)){return PlayerPrefs.GetInt(keyName,0);}else if(fieldType typeof(float)){return PlayerPrefs.GetFloat(keyName,0);}else if(fieldType typeof(string)){return PlayerPrefs.GetString(keyName,);}else if(fieldType typeof(bool)){//自定义存储bool值规则return PlayerPrefs.GetInt(keyName,0) 1 ? true : false;}else if(typeof(IList).IsAssignableFrom(fieldType)){//得到长度int count PlayerPrefs.GetInt(keyName,0);//实例化一个List对象进行赋值IList list Activator.CreateInstance(fieldType) as IList;for(int i 0;i count;i){//得到List中泛型的类型list.Add(LoadValue(fieldType.GetGenericArguments()[0],keyName i));}return list;}else if(typeof(IDictionary).IsAsssignableFrom(fieldType)){//得到字典的长度int count PlayerPrefs.GetInt(keyName,0);//实例化一个字典对象用父类装子类IDictionary dic Activator.CreateInstance(fieldType);Type[] kvType fieldType.GetGenericArguments();for(int i 0;i count;i){dic.Add(LoadValue(kvType[0],keyName _key_ i),LoadValue(kvType[1],keyName _value_ i));}return dic;}return null;
}反射读取数据----自定义类成员
private object LoadValue(Type fieldType,string keyName)
{//根据字段类型判断用哪个API读取if(fieldType typeof(int)){return PlayerPrefs.GetInt(keyName,0);}else if(fieldType typeof(float)){return PlayerPrefs.GetFloat(keyName,0);}else if(fieldType typeof(string)){return PlayerPrefs.GetString(keyName,);}else if(fieldType typeof(bool)){//自定义存储bool值规则return PlayerPrefs.GetInt(keyName,0) 1 ? true : false;}else if(typeof(IList).IsAssignableFrom(fieldType)){//得到长度int count PlayerPrefs.GetInt(keyName,0);//实例化一个List对象进行赋值IList list Activator.CreateInstance(fieldType) as IList;for(int i 0;i count;i){//得到List中泛型的类型list.Add(LoadValue(fieldType.GetGenericArguments()[0],keyName i));}return list;}else if(typeof(IDictionary).IsAsssignableFrom(fieldType)){//得到字典的长度int count PlayerPrefs.GetInt(keyName,0);//实例化一个字典对象用父类装子类IDictionary dic Activator.CreateInstance(fieldType);Type[] kvType fieldType.GetGenericArguments();for(int i 0;i count;i){dic.Add(LoadValue(kvType[0],keyName _key_ i),LoadValue(kvType[1],keyName _value_ i));}return dic;} else {return LoadData(fieldType,keyName);}return null;
}加密思路
找不到 1、把存在硬盘上的内容放在一个不容易找到的地方 2、多层文件夹包裹 3、名字辨识度低 但是对于PlayerPrefs不太适用因为位置已经固定了改不了。 看不懂 让数据的key和value让别人看不懂俗称加密为key和value加密。 解不出 不让别人获取到你加密的规则。 注意 单机游戏加密只是提高别人修改你数据的门槛只要别人获取到你的源代码知道你的加密规则一切都没有任何意义。但是对于一般玩家来说几乎是不可能的事情。
生成资源包