您现在的位置是:首页 >学无止境 >【unity数据持久化】游戏排行榜信息简单的存储,你还知道吗?数据管理类_PlayerPrfs网站首页学无止境

【unity数据持久化】游戏排行榜信息简单的存储,你还知道吗?数据管理类_PlayerPrfs

秩沅 2024-09-09 00:01:02
简介【unity数据持久化】游戏排行榜信息简单的存储,你还知道吗?数据管理类_PlayerPrfs

在这里插入图片描述


?‍?个人主页@元宇宙-秩沅

?‍? hallo 欢迎 点赞? 收藏⭐ 留言? 加关注✅!

?‍? 本文由 秩沅 原创

?‍? 收录于专栏unity数据存储

请添加图片描述


制作一个数据管理类(存储排行榜信息)的实践

Unity公共类PlayerPrefs知识点入口


?需求分析


在这里插入图片描述


?关键知识补充


在这里插入图片描述


?数据管理类的创建


在这里插入图片描述


?PlayerPrefs—各种类型的反射存储框架


在这里插入图片描述

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Unity.VisualScripting;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:       ______________
//___________功能: 数据管理存储  
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------


public class PlayerfabsClass
{
    //单例模式的构建
    static private PlayerfabsClass chats = new PlayerfabsClass();
    static public  PlayerfabsClass Chats { get => chats; }
    //private List<object> listMess;
    //private Dictionary<object, object> dictionaryMess;

    /// <summary>
    /// 实现对象的数据的存储
    /// </summary>
    /// <param  name="player">玩家对象</param>
    /// <param  name="palyName">玩家对象信息Key字符</param>
    public void SaveDataMess(object  player ,string playName)
    {
        //-关键作用-:通过排行中的值来获取其信息

        //自定义key的规则通过反射来获取对象里面的-类型名-和-类型值-
       
        Type type = player.GetType();
        Debug.Log(type);     
        FieldInfo[] FieldsMess = type.GetFields();
        for (int i = 0; i < FieldsMess.Length; i++)
        {
            Debug.Log(FieldsMess[i]);
        }
        
        string temp = null;      
        for (int i = 0; i < FieldsMess.Length; i++)  //通过字符串的拼接来,使得存储的字段具有唯一性
        {
            temp = $"{playName}_{type}_{FieldsMess[i].FieldType.Name}_{FieldsMess[i].Name }";
            Debug.Log(playName);
            HelpSave( FieldsMess[i].GetValue(player) ,temp );
        }
        PlayerPrefs.Save();      
    }

    /// <summary>
    /// 辅助存储
    /// </summary>
    /// <param name="value">由于只能设置三种类型的值就不得不用方法来进行</param>
    /// <param name="playName">已经拼接好的key字符串</param>
    private void HelpSave(object value , string playName )
    {
       Type valueTpye = value.GetType();
        //----------1.常用数据类型的反射存储
        if (valueTpye == typeof(int))
        {
            Debug.Log((int)value);
            PlayerPrefs.SetInt(playName, (int)value);
        } 
       else  if (valueTpye == typeof(float ))
        {
            Debug.Log((float )value);
            PlayerPrefs.SetFloat(playName, (float)value);
        }
       else  if (valueTpye == typeof(string))
        {
            Debug.Log(value.ToString());
            PlayerPrefs.SetString(playName, value.ToString());
        }
        //----------2.泛型List数据类型的反射存储 ——递归
       else if(valueTpye.IsAssignableFrom(typeof(IList)) == true)  //因为泛型不确定无法判断所以通过(判断是否为子类的API)确定类型
        {
            IList list = valueTpye as IList;
            int index = 0;
            PlayerPrefs.SetInt(playName,list.Count);  //存储List数据先存储数量
            foreach (object  item in list  )
            {
                HelpSave(item, item + "_" + index);
            }
        }
        //--------3.泛型字典数据类型的反射存储 —— 递归
        else if(valueTpye.IsAssignableFrom(typeof(IDictionary) )==true)
        {
            IDictionary dictionary = valueTpye as IDictionary;
            int index = 0;
            PlayerPrefs.SetInt(playName,dictionary.Count );
            foreach (object item in dictionary .Keys)
            {
                HelpSave(item,item+"_Key_"+ index );
                HelpSave(dictionary[item], dictionary[item] + "_Vaule_" + index);
            }

        }
        //--------4.自定义类型的数据的反射存储 —— 大递归
        else 
        {
            SaveDataMess(value ,playName);
        }
    }



     
}


?PlayerPrefs—存储主方法


在这里插入图片描述

 public void SaveDataMess(object player, string playName)
    {
        //-关键作用-:通过排行中的值来获取其信息

        //自定义key的规则通过反射来获取对象里面的-类型名-和-类型值-

        Type type = player.GetType();
        Debug.Log(type);
        FieldInfo[] FieldsMess = type.GetFields();
        for (int i = 0; i < FieldsMess.Length; i++)
        {
            Debug.Log(FieldsMess[i]);
        }

        string temp = null;
        for (int i = 0; i < FieldsMess.Length; i++)  //通过字符串的拼接来,使得存储的字段具有唯一性
        {
            temp = $"{playName}_{type}_{FieldsMess[i].FieldType.Name}_{FieldsMess[i].Name }";
            Debug.Log(playName);
            HelpSave(FieldsMess[i].GetValue(player), temp);
        }
        PlayerPrefs.Save();
    }

?PlayerPrefs—普通数据类型的反射存储


在这里插入图片描述

//-------------------------------------
//—————————————————————————————————————
//___________项目:       ______________
//___________功能: 数据管理存储     
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------

public class PlayerfabsClass
{
    //单例模式的构建
    static private PlayerfabsClass chats = new PlayerfabsClass();
    static public  PlayerfabsClass Chats { get => chats; }
    //private List<object> listMess;
    //private Dictionary<object, object> dictionaryMess;

    /// <summary>
    /// 实现对象的数据的存储
    /// </summary>
    /// <param  name="player">玩家对象</param>
    /// <param  name="palyName">玩家对象信息Key字符</param>
    public void SaveDataMess(object  player ,string playName)
    {
        //-关键作用-:通过排行中的值来获取其信息

        //自定义key的规则通过反射来获取对象里面的-类型名-和-类型值-
       
        Type type = player.GetType();
        Debug.Log(type);     
        FieldInfo[] FieldsMess = type.GetFields();
        for (int i = 0; i < FieldsMess.Length; i++)
        {
            Debug.Log(FieldsMess[i]);
        }
        
        string temp = null;      
        for (int i = 0; i < FieldsMess.Length; i++)  //通过字符串的拼接来,使得存储的字段具有唯一性
        {
            temp = $"{playName}_{type}_{FieldsMess[i].FieldType.Name}_{FieldsMess[i].Name }";
            Debug.Log(playName);
            HelpSave( FieldsMess[i].GetValue(player) ,temp );
        }
        PlayerPrefs.Save();      
    }

    /// <summary>
    /// 辅助存储
    /// </summary>
    /// <param name="value">由于只能设置三种类型的值就不得不用方法来进行</param>
    /// <param name="playName">已经拼接好的key字符串</param>
    private void HelpSave(object value , string playName )
    {
       Type valueTpye = value.GetType();
        if (valueTpye == typeof(int))
        {
            Debug.Log((int)value);
            PlayerPrefs.SetInt(playName, (int)value);
        } 
       else  if (valueTpye == typeof(float ))
        {
            Debug.Log((float )value);
            PlayerPrefs.SetFloat(playName, (float)value);
        }
       else  if (valueTpye == typeof(string))
        {
            Debug.Log(value.ToString());
            PlayerPrefs.SetString(playName, value.ToString());
        }
    }

    /// <summary>
    /// 实现对象的读取
    /// </summary>
    public void ReadMess()
    {

    }


?PlayerPrefs—泛型List的反射存储


在这里插入图片描述

在这里插入图片描述

   //----------2.泛型List数据类型的反射存储
       else if(valueTpye.IsAssignableFrom(typeof(IList)) == true)  //因为泛型不确定无法判断所以通过(判断是否为子类的API)确定类型
        {
            IList list = valueTpye as IList;
            int index = 0;
            PlayerPrefs.SetInt(playName,list.Count);  //存储List数据先存储数量
            foreach (object  item in list  )
            {
                HelpSave(item, item + "_" + index);
            }
        }

?PlayerPrefs—泛型Dictionary的反射存储


在这里插入图片描述

 //--------3.泛型字典数据类型的反射存储 —— 递归
        else if(valueTpye.IsAssignableFrom(typeof(IDictionary) )==true)
        {
            IDictionary dictionary = valueTpye as IDictionary;
            int index = 0;
            PlayerPrefs.SetInt(playName,dictionary.Count );
            foreach (object item in dictionary .Keys)
            {
                HelpSave(item,item+"_Key_"+ index );
                HelpSave(dictionary[item], dictionary[item] + "_Vaule_" + index);
            }

        }

?PlayerPrefs—自定义类类型的反射存储


在这里插入图片描述

        //--------4.自定义类型的数据的反射存储 —— 大递归
        else 
        {
            SaveDataMess(value ,playName);
        }

?PlayerPrefs—各种类型的反射获取框架


在这里插入图片描述

 #region 获取和赋值
    /// <summary>
    /// 获取存的数据,返回一个对象
    /// </summary>
    /// <param name="data"></param>
    /// <param name="playName"></param>
    /// <returns></returns>
    public object GetDataMess(Type data ,string playName)
    {
        object player = Activator.CreateInstance(data) ;
        
        FieldInfo[] info = data.GetFields();

        string temp = "" ; 

        for (int i = 0; i < info.Length; i++)
        {
            
            temp = $"{playName}_{data}_{info[i].FieldType.Name}_{info [i].Name }";
            //遍历每一个成员传进去设值
            info[i].SetValue(data ,HelpSet(info[i].FieldType ,temp));
        }
        //给所有成员都设置值
        

        return player;
    }


    public object HelpSet(Type type ,string playName)
    {

        //----------1.常用数据类型的反射获取
        if (type == typeof(int) )
        {
          return PlayerPrefs.GetInt(playName,0); //第二个重载为设置默认值
        }
        else if(type == typeof(float))
        {
            return PlayerPrefs.GetFloat(playName, 0);
        }
        else if (type == typeof(string ))
        {
            return PlayerPrefs.GetString(playName, "");
        }
        else if(type ==typeof(bool))
        {
            return PlayerPrefs.GetInt(playName, 0) == 1 ? true : false;
        }

        //----------2.泛型List数据类型的反射获取
        else if (type.IsAssignableFrom(typeof(IList)) == true)
        {
            //此时list也是对象了要实例化
            IList list = Activator.CreateInstance(type) as IList;

            Type Ftype = type.GetGenericArguments()[0];  //一个泛型返回下标0即可
          
            int Count = PlayerPrefs.GetInt(playName + "_" + "Number");
        
            for (int i = 0; i < Count; i++)
            {               
                list.Add(HelpSet(Ftype , playName + "_" + i));
            }
            
            return list;
        }
        //--------3.泛型字典数据类型的反射获取 

        else if (type.IsAssignableFrom(typeof(IDictionary)) == true)
        {
            //此时list也是对象了要实例化
            IDictionary dictionary = Activator.CreateInstance(type) as IDictionary;

            Type Ftype1 = type.GetGenericArguments()[0];  //一个泛型返回下标0即可
            Type Ftype2 = type.GetGenericArguments()[1];

            int Count = PlayerPrefs.GetInt(playName + "_" + "Number");

            for (int i = 0; i < Count; i++)
            {
                dictionary.Add(HelpSet(Ftype1, playName + "_" + i),
                               HelpSet(Ftype1, playName + "_" + i ) );
            }

            return dictionary;
        }

        else
        {
            GetDataMess(type, playName);
        }
        return null;
    }
    #endregion

?PlayerPrefs—获取主方法


    public object GetDataMess(Type data ,string playName)
    {
        object player = Activator.CreateInstance(data) ;
        
        FieldInfo[] info = data.GetFields();

        string temp = "" ; 

        for (int i = 0; i < info.Length; i++)
        {
            
            temp = $"{playName}_{data}_{info[i].FieldType.Name}_{info [i].Name }";
            //遍历每一个成员传进去设值
            info[i].SetValue(data ,HelpSet(info[i].FieldType ,temp));
        }
        //给所有成员都设置值
        

        return player;
    }

?PlayerPrefs—普通数据类型的反射获取


在这里插入图片描述

 //----------1.常用数据类型的反射获取
        if (type == typeof(int) )
        {
          return PlayerPrefs.GetInt(playName,0); //第二个重载为设置默认值
        }
        else if(type == typeof(float))
        {
            return PlayerPrefs.GetFloat(playName, 0);
        }
        else if (type == typeof(string ))
        {
            return PlayerPrefs.GetString(playName, "");
        }
        else if(type ==typeof(bool))
        {
            return PlayerPrefs.GetInt(playName, 0) == 1 ? true : false;
        }

?PlayerPrefs—泛型List的反射获取


在这里插入图片描述

   //----------2.泛型List数据类型的反射获取
        else if (type.IsAssignableFrom(typeof(IList)) == true)
        {
            //此时list也是对象了要实例化
            IList list = Activator.CreateInstance(type) as IList;

            Type Ftype = type.GetGenericArguments()[0];  //一个泛型返回下标0即可
          
            int Count = PlayerPrefs.GetInt(playName + "_" + "Number");
        
            for (int i = 0; i < Count; i++)
            {               
                list.Add(HelpSet(Ftype , playName + "_" + i));
            }
            
            return list;
        }

?PlayerPrefs—泛型Dictionary的反射获取


在这里插入图片描述

 //--------3.泛型字典数据类型的反射获取 

        else if (type.IsAssignableFrom(typeof(IDictionary)) == true)
        {
            //此时list也是对象了要实例化
            IDictionary dictionary = Activator.CreateInstance(type) as IDictionary;

            Type Ftype1 = type.GetGenericArguments()[0];  //一个泛型返回下标0即可
            Type Ftype2 = type.GetGenericArguments()[1];

            int Count = PlayerPrefs.GetInt(playName + "_" + "Number");

            for (int i = 0; i < Count; i++)
            {
                dictionary.Add(HelpSet(Ftype1, playName + "_" + i),
                               HelpSet(Ftype1, playName + "_" + i ) );
            }

            return dictionary;
        }

?PlayerPrefs—自定义类类型的反射存储


在这里插入图片描述

else
        {
            GetDataMess(type, playName);
        }

?PlayerPrefs—排行榜管理最终代码


在这里插入图片描述

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Unity.VisualScripting;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:       ______________
//___________功能: 数据管理类     
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------


public class PlayerfabsClass
{
    //单例模式的构建
    static private PlayerfabsClass chats = new PlayerfabsClass();
    static public PlayerfabsClass Chats { get => chats; }
    //private List<object> listMess;
    //private Dictionary<object, object> dictionaryMess;

    /// <summary>
    /// 实现对象里的数据的存储
    /// </summary>
    /// <param  name="player">玩家对象</param>
    /// <param  name="palyName">玩家对象信息Key字符</param>
    /// 


    public void SaveDataMess(object player, string playName)
    {
        //-关键作用-:通过排行中的值来获取其信息

        //自定义key的规则通过反射来获取对象里面的-类型名-和-类型值-

        Type type = player.GetType();
        Debug.Log(type);
        FieldInfo[] FieldsMess = type.GetFields();
        for (int i = 0; i < FieldsMess.Length; i++)
        {
            Debug.Log(FieldsMess[i]);
        }

        string temp = null;
        for (int i = 0; i < FieldsMess.Length; i++)  //通过字符串的拼接来,使得存储的字段具有唯一性
        {
            temp = $"{playName}_{type}_{FieldsMess[i].FieldType.Name}_{FieldsMess[i].Name }";
            Debug.Log(playName);
            HelpSave(FieldsMess[i].GetValue(player), temp);
        }
        PlayerPrefs.Save();
    }

    /// <summary>
    /// 辅助存储
    /// </summary>
    /// <param name="value">由于只能设置三种类型的值就不得不用方法来进行</param>
    /// <param name="playName">已经拼接好的key字符串</param>
    private void HelpSave(object value, string playName)
    {
        Type valueTpye = value.GetType();
        //----------1.常用数据类型的反射存储
        if (valueTpye == typeof(int))
        {
            Debug.Log((int)value);
            PlayerPrefs.SetInt(playName, (int)value);
        }
        else if (valueTpye == typeof(float))
        {
            Debug.Log((float)value);
            PlayerPrefs.SetFloat(playName, (float)value);
        }
        else if (valueTpye == typeof(string))
        {
            Debug.Log(value.ToString());
            PlayerPrefs.SetString(playName, value.ToString());
        }
        else if(valueTpye == typeof(bool))
        {
            Debug.Log(value.ToString());
            PlayerPrefs.SetInt(playName,(bool)value?1:0);
        }
        //----------2.泛型List数据类型的反射存储 ——递归

        else if (valueTpye.IsAssignableFrom(typeof(IList)) == true)  //因为泛型不确定无法判断所以通过(判断是否为子类的API)确定类型
        {
            IList list = valueTpye as IList;
            int index = 0;
            PlayerPrefs.SetInt(playName+"_"+"Number", list.Count);  //存储List数据先存储数量
            foreach (object item in list)
            {
                HelpSave(item, playName + "_" + index);
                index++;
            }
        }
        //--------3.泛型字典数据类型的反射存储 —— 递归

        else if (valueTpye.IsAssignableFrom(typeof(IDictionary)) == true)
        {
            IDictionary dictionary = valueTpye as IDictionary;
            int index = 0;
            PlayerPrefs.SetInt(playName+ "_" + "Number", dictionary.Count); //先存储数量
            foreach (object item in dictionary.Keys)
            {
                HelpSave(item, playName + "_Key_" + index);
                HelpSave(dictionary[item], playName + "_Vaule_" + index);
                index++;
            }

        }
        //--------4.自定义类型的数据的反射存储 —— 大递归
        else
        {
            SaveDataMess(value, playName);
        }
    }

    #region 获取和赋值
    /// <summary>
    /// 获取存的数据,返回一个对象
    /// </summary>
    /// <param name="data"></param>
    /// <param name="playName"></param>
    /// <returns></returns>
    public object GetDataMess(Type data ,string playName)
    {
        object player = Activator.CreateInstance(data) ;
        
        FieldInfo[] info = data.GetFields();

        string temp = "" ; 

        for (int i = 0; i < info.Length; i++)
        {
            
            temp = $"{playName}_{data}_{info[i].FieldType.Name}_{info [i].Name }";
            //遍历每一个成员传进去设值
            info[i].SetValue(data ,HelpSet(info[i].FieldType ,temp));
        }
        //给所有成员都设置值
        

        return player;
    }


    public object HelpSet(Type type ,string playName)
    {

        //----------1.常用数据类型的反射获取
        if (type == typeof(int) )
        {
          return PlayerPrefs.GetInt(playName,0); //第二个重载为设置默认值
        }
        else if(type == typeof(float))
        {
            return PlayerPrefs.GetFloat(playName, 0);
        }
        else if (type == typeof(string ))
        {
            return PlayerPrefs.GetString(playName, "");
        }
        else if(type ==typeof(bool))
        {
            return PlayerPrefs.GetInt(playName, 0) == 1 ? true : false;
        }

        //----------2.泛型List数据类型的反射获取
        else if (type.IsAssignableFrom(typeof(IList)) == true)
        {
            //此时list也是对象了要实例化
            IList list = Activator.CreateInstance(type) as IList;

            Type Ftype = type.GetGenericArguments()[0];  //一个泛型返回下标0即可
          
            int Count = PlayerPrefs.GetInt(playName + "_" + "Number");
        
            for (int i = 0; i < Count; i++)
            {               
                list.Add(HelpSet(Ftype , playName + "_" + i));
            }
            
            return list;
        }
        //--------3.泛型字典数据类型的反射获取 

        else if (type.IsAssignableFrom(typeof(IDictionary)) == true)
        {
            //此时list也是对象了要实例化
            IDictionary dictionary = Activator.CreateInstance(type) as IDictionary;

            Type Ftype1 = type.GetGenericArguments()[0];  //一个泛型返回下标0即可
            Type Ftype2 = type.GetGenericArguments()[1];

            int Count = PlayerPrefs.GetInt(playName + "_" + "Number");

            for (int i = 0; i < Count; i++)
            {
                dictionary.Add(HelpSet(Ftype1, playName + "_" + i),
                               HelpSet(Ftype1, playName + "_" + i ) );
            }

            return dictionary;
        }

        else
        {
            GetDataMess(type, playName);
        }
        return null;
    }
    #endregion
    #region 打印对象里面的信息
    /// <summary>
    /// 读取信息函数
    /// </summary>
    /// <param name="type">为什么这里不用Object用type,因为读取没有值,只需要类型就行简化了代码 </param>
    /// <param name="playName">还是原来的Key关键标识字符</param>
    public void ReadData(Type type ,string playName)
    {
        string temp = "";
        //----------1.常用数据类型的反射打印
        if (type == typeof(int))
        {
            Debug.Log(PlayerPrefs.GetInt(playName));
        }
        else if(type == typeof(float) )
        {
            Debug.Log(PlayerPrefs.GetFloat(playName));
        }
        else if (type == typeof(string) )
        {
            Debug.Log(PlayerPrefs.GetString(playName));
        }
        //----------2.泛型List数据类型的反射打印 ——递归

        else if (type.IsAssignableFrom(typeof(IList)) )
        {
            IList list = type as IList;
            Debug.Log( PlayerPrefs.GetInt(playName +"_" + "Number") ); //先读取数量
            int index = 0;
            foreach (Type item in list )
            {
                ReadData(item, playName + "_" + index);
                index++;
            }
        }


        //--------3.泛型字典数据类型的反射打印 —— 递归

        else if (type.IsAssignableFrom(typeof(IDictionary)))
        {
            IDictionary dictionary = type as IDictionary;
            int index = 0;
            PlayerPrefs.GetInt(playName + "_" + "Number"); //先读取数量
            foreach (Type item in dictionary.Keys)
            {
                ReadData(item, playName + "_Key_" + index);
                ReadData(item, playName + "_Vaule_" + index);
                index++;
            }
        }
        //--------4.自定义类型的数据的反射打印 —— 大递归
        else
        {
            FieldInfo[] FieldsMess = type.GetFields();
           
          for (int i = 0; i < FieldsMess.Length; i++) //成员递归下去
            {
                temp = $"{playName}_{type}_{FieldsMess[i].FieldType.Name}_{FieldsMess[i].Name }";
              
                ReadData(FieldsMess[i].FieldType , playName);
            }
        }
        

    }
    #endregion 


}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:       ______________
//___________功能: 排行榜数据控制器     
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class Contorl : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Player player1 = new Player("孙悟空","BBBBB",66,10);
        //存
        PlayerfabsClass.Chats.SaveDataMess(player1,player1.playName);
        //取
        PlayerfabsClass.Chats.GetDataMess(player1.GetType(),player1.playName);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}


⭐相关文章⭐

【2023unity游戏制作-mango的冒险】-4.场景二的镜头和法球特效跟随

【2023unity游戏制作-mango的冒险】-3.基础动作和动画API实现

【2023unity游戏制作-mango的冒险】-2.始画面API制作

【2023unity游戏制作-mango的冒险】-1.场景搭建

“狂飙”游戏制作—游戏分类图鉴(网易游学)

本站最全-unity常用API大全(万字详解),不信你不收藏



你们的点赞? 收藏⭐ 留言? 关注✅是我持续创作,输出优质内容的最大动力!

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。