首页 > 其他分享 >Unity学习笔记--数据持久化之PlayerPrefs的使用

Unity学习笔记--数据持久化之PlayerPrefs的使用

时间:2023-11-19 20:45:39浏览次数:32  
标签:存储 name -- int Unity PlayerPrefs type public

数据持久化

PlayerPrefs相关

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

//PlayerPrefs的数据存储 类似于键值对存储 一个键对应一个值
//提供了存储3种数据的方法 int float string
//键: string类型 
//值:int float string 对应3种API

PlayerPrefs.SetInt("myAge", 18);
PlayerPrefs.SetFloat("myHeight", 177.5f);
PlayerPrefs.SetString("myName", "TonyChang");

//直接调用Set相关方法 只会把数据存到内存里
//当游戏结束时 Unity会自动把数据存到硬盘中
//如果游戏不是正常结束的 而是崩溃 数据是不会存到硬盘中的
//只要调用该方法 就会马上存储到硬盘中
PlayerPrefs.Save();

//PlayerPrefs是有局限性的 它只能存3种类型的数据
//如果你想要存储别的类型的数据 只能降低精度 或者上升精度来进行存储
bool sex = true;
PlayerPrefs.SetInt("sex", sex ? 1 : 0);

//如果不同类型用同一键名进行存储 会进行覆盖
PlayerPrefs.SetFloat("myAge", 20.2f);

//注意 运行时 只要你Set了对应键值对
//即使你没有马上存储Save在本地
//也能够读取出信息

//int
int age = PlayerPrefs.GetInt("myAge");
print(age);
//前提是 如果找不到myAge对应的值 就会返回函数的第二个参数 默认值
age = PlayerPrefs.GetInt("myAge", 100);
print(age);

//float
float height = PlayerPrefs.GetFloat("myHeight", 1000f);
print(height);

//string
string name = PlayerPrefs.GetString("myName");
print(name);

//第二个参数 默认值 对于我们的作用
//就是 在得到没有的数据的时候 就可以用它来进行基础数据的初始化

//判断数据是否存在
if( PlayerPrefs.HasKey("myName") )
{
    print("存在myName对应的键值对数据");
}

//删除指定键值对
PlayerPrefs.DeleteKey("myAge");
//删除所有存储的信息
PlayerPrefs.DeleteAll();

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

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

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

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

优点:使用简单

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

PlayerPrefs存储工具类:

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

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

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>
        /// 存取数据的方法
        /// </summary>
        /// <param name="obj">数据实体</param>
        /// <param name="name">数据名称</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++)
            {
                //获取数据数据类型
                tempInfo = infos[i];
                Debug.Log("Types==="+tempInfo);
                //类的名字+类的类型 + 数据内容名字+数据类型
                //作为存储的keyName键
                tempKey = keyName + "_" + type.Name + "_" + tempInfo.Name
                            + "_" + tempInfo.FieldType.Name;
                SaveValue(tempInfo.GetValue(data),tempKey);
            }
            //进行值的获取
           //tempInfo.GetValue(data);
            PlayerPrefs.Save();
        }
        /// <summary>
        /// 读取数据的类型
        /// </summary>
        /// <param name="type">要读取的数据类型</param>
        /// <param name="name">要读取的数据名称</param>
        /// <returns>返回数据实体</returns>
        public object LoadData(Type type, string name)
        {
            //获取数据中的类型
            FieldInfo[] infos = type.GetFields();
            //创建存储数据信息的实体
            object data = Activator.CreateInstance(type);
            string tempName = null;
            FieldInfo tempInfo = null;
            for (int i = 0; i < infos.Length; i++)
            {
                tempInfo = infos[i];//数据结构中的数据名称
                tempName = name + "_" + type.Name + "_" +tempInfo.Name+"_"
                    +tempInfo.FieldType.Name;//数据结构中的数据名称类型
                //装载的容器  容器中的数据 
                //进行数据装载
                tempInfo.SetValue(data,LoadValue(tempInfo.FieldType,tempName));
            }
            return data;
        }

        /// <summary>
        /// 进行具体的类型数据的存储
        /// </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存储的设置
            //根据存储的字段类型和IList是否是父子关系
            else if(typeof(IList).IsAssignableFrom(fieldType))
            {
                //父类装子类
                IList list=value as IList;
                //存储元素数量
                PlayerPrefs.SetInt(keyName,list.Count);
                Debug.Log("存储List长度为"+list.Count);
                int index = 0;
                foreach (var obj in list)
                {
                    //存储list列表中元素内容
                    //命名形式是 list名字+索引编号
                    //递归调用存储
                    SaveValue(obj,keyName+index);
                    index++;
                }
            }else if (typeof(IDictionary).IsAssignableFrom(fieldType))
            {
                IDictionary dictionary = value as IDictionary;
                //存储数据个数
                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++;
                }
            }//自定义数据类型的存储 进行解析
            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))
            {
                //进行对字典的读取
                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
            {
                //读取自定义类成员的设置
                return LoadData(type, name);
            }
        }
    }
}

附:

测试脚本

using System.Collections.Generic;
using UnityEngine;

namespace Framwork
{
    //注意:
    //1 自定义数据结构类型中要有有效的无参构造函数
    
    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;//学号
        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()
        {
             //读取数据
             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");

             //进行数据保存
             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]);
        }
    }
}

标签:存储,name,--,int,Unity,PlayerPrefs,type,public
From: https://www.cnblogs.com/TonyCode/p/17842598.html

相关文章

  • 什么是 2B 软件的实施和上线概念
    首先,我们需要明确"2B"这个词的含义。在商业领域,"2B"是"BusinesstoBusiness"的简称,指的是企业对企业的商业模式。在这种模式下,一家企业提供的产品或服务是为其他企业提供的,而不是直接面向消费者。在计算机软件领域,"2B软件"指的是为企业或组织提供的软件产品或服务。这种......
  • 学期:2023-2024-1 学号:20231426 《计算机基础与程序设计》第八周学习总结
    作业信息这个作业属于哪个课程2022-2023-1-计算机基础与程序设计这个作业要求在哪里2022-2023-1计算机基础与程序设计作业这个作业的目标通过教材内容了解函数、模块化设计、作业正文https://www.cnblogs.com/hhaxx/p/17842602.html教材学习内容总结《计......
  • (lora训练补充数据)父目录镜像
    importosfromPILimportImagedefflip_and_duplicate_image(image_path,output_path):"""Flipanimagehorizontallyandsaveacopywithasuffix."""try:withImage.open(image_path)asimg:......
  • 四则
    从《构建之法》第一章的“程序”例子出发,像阿超那样,花二十分钟写一个能自动生成小学四则运算题目的命令行“软件”,满足以下需求:(以下参考博客链接:http://www.cnblogs.com/jiel/p/4810756.html)使用C实现四则运算参考https://www.cnblogs.com/saiwa/articles/5253713.html学习......
  • 俄罗斯方块游戏
    上网查阅了一些通过编程实现俄罗斯方块的文章,对于现在的我来说实在是太难。可以等以后技术再高一点再进行尝试。......
  • 2023-2024-1 学号20231318《计算机基础与程序设计》第8周学习总结
    作业信息这个作业属于哪个课程2022-2023-1-计算机基础与程序设计这个作业要求在哪里2022-2023-1计算机基础与程序设计第八周作业这个作业的目标自学教材《计算机科学概论》第9章以及《C语言程序设计》第7章并完成云班课测试。作业正文2023-2024-1学号20231318......
  • 关于 SAP BMBC 批次查询结果 BADI - BIC_ADDITIONAL_DATA 的案例
    在SAP中,BADI(BusinessAdd-In)是一种用户扩展点,可以使用它来插入我们自己的业务逻辑,而不会影响到标准的应用程序。在ABAP中,我们经常需要使用BADI来满足特定的业务需求。在本文中,我们将介绍一个关于BMBC批次查询结果BADI-BIC_ADDITIONAL_DATA的案例。BMBC是SAP的一个......
  • 8.5 Windows驱动开发:内核注册表增删改查
    注册表是Windows中的一个重要的数据库,用于存储系统和应用程序的设置信息,注册表是一个巨大的树形结构,无论在应用层还是内核层操作注册表都有独立的API函数可以使用,而在内核中读写注册表则需要使用内核装用API函数,如下将依次介绍并封装一些案例,实现对注册表的创建,删除,更新,查询等操作......
  • 安装llama.cpp遇到的问题
    llama.cpp在ubuntu环境下编译: 1.下载好模型文件,如llama-2-7b-chat-hf; Mistral-7B-Instruct-v0.1/ggml-model-f16-q8_0.gguf2.建立conda环境condacreate-nllamacpppython=3.103.condaactivatellamacpp4.pipinstallsentencepiecegguf 安装好nvidia-smi,nvcc......
  • BLOG-2
    作业总结1.1前言这几次作业主要是对菜单计价程序的完善,第四次作业中的菜单计价程序2是在菜单计价程序1的基础上进行完善,添加了输入菜单和份额的要求,难度还在可以接受的范围。第四次作业中的菜单计价程序3则是在菜单计价程序2的基础上添加了一系列的要求,包括添加桌号、代点菜......