学习目标:

  如果你和我同样苦恼于游戏相关的数据怎么存储与读取,那么不妨看看这个up主有关Unity存档系统的教程。[Unity] 存档系统 Part 1 | PlayerPrefs | Unity初学者系列教程 | 数据存取 | 存档读档 | Save&Load_哔哩哔哩_bilibili在本视频中你将学到Unity引擎中三种常见的数据存储方式中的第一种:PlayerPrefs主要内容:什么是PlayerPrefs如何使用PlayerPrefsPlayerPrefs的优缺点以及适用范围构建一个基于PlayerPrefs的基础数据存取系统Unity存档系统第二部分 - JSON:BV1Cb4y1b71G————————————————————你好啊,我是阿严,一个小小的独立游戏开发者icon-default.png?t=N7T8https://www.bilibili.com/video/BV1nQ4y1z7pZ/?spm_id_from=333.788.recommend_more_video.-1

这里我将up主讲到的内容作为笔记,先给大伙开个头介绍PlayerPrefs。


学习内容:

  根据官网的API的定义,`PlayerPrefs`是一个在游戏会话之间存储玩家首选项的类。它可以将字符串、浮点和整数值存储到用户的平台注册表中。由此可见,他能存储string,int,float类型的数据到计算机的数据表中,这就注定了它只能存储简单的数据,玩家的偏好选项例如音量设置等,下面不妨通过一个项目简单了解一下怎么使用。

   这里使用的是up主的GitHub素材,有一个现成的场景,这里我想重头开始写,把Player和UI上挂载的脚本全部删了,再新建一个NewPlayer然后就到了脚本的时间

首先是NewPlayer脚本,我们创建两个私有函数用啦保存和读取PlayerPrefs上的数据,两个public函数用来给按钮的点击事件。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SaveSystemTur
{
    public class NewPlayerData : MonoBehaviour
    {
        private const string PLAYER_DATA_KEY = "PlayerData";
        #region Fields
        [SerializeField] string playerName = "";
        [SerializeField] int coin = 0;
        [SerializeField] int level = 0;

        [System.Serializable]
        class SaveData
        {
            public string playerName;
            public int playerLevel;
            public int playerCoin;
            public Vector3 playerPosition;
        }

        #endregion

        #region Propertries

        public string PlayerName => playerName;
        public int Coin => coin;
        public int Level => level;

        public Vector3 Position => transform.position;
        #endregion

        #region Save And Load
        public void Save()
        {
            SaveByPlayerPrefs();
        }
        public void Load()
        {
            LoadFromPlayerPrefs();
        }
        #region PlayerPrefs
        void SaveByPlayerPrefs()
        {
            PlayerPrefs.SetInt("PlayerLevel", level);
            PlayerPrefs.SetInt("PlayerCoin", coin);

            PlayerPrefs.SetFloat("PlayerPositionX", transform.position.x);
            PlayerPrefs.SetFloat("PlayerPositionY", transform.position.y);
            PlayerPrefs.SetFloat("PlayerPositionZ", transform.position.z);
        }

        

        void LoadFromPlayerPrefs()
        {
            
            playerName = PlayerPrefs.GetString("PlayerName", "Somebody");

            level = PlayerPrefs.GetInt("PlayerLevel");
            coin = PlayerPrefs.GetInt("PlayerCoin");

            transform.position = new Vector3(PlayerPrefs.GetFloat("PlayerPositionX"), PlayerPrefs.GetFloat("PlayerPositionY"), PlayerPrefs.GetFloat("PlayerPositionZ"));
        }

        

        
}

这里涉及到的有PlayerPrefs.Set****(),PlayerPrefs.Get****().

然后再UI函数中

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace SaveSystemTur
{
    public class NewUIController : MonoBehaviour
    {
        #region Propertries
        [Header("============ Text ==========")]
        [SerializeField] Text playerNameText;
        [SerializeField] Text playerLevelText;
        [SerializeField] Text playerCoinText;
        [SerializeField] Text playerPositionX;
        [SerializeField] Text playerPositionY;
        [SerializeField] Text playerPositionZ;

        [Header("============ Button ========")]
        [SerializeField] Button saveButton;
        [SerializeField] Button loadButton;

        [SerializeField] NewPlayerData newPlayerData;
        #endregion
        void Start()
        {
            saveButton.onClick.AddListener(newPlayerData.Save);
            loadButton.onClick.AddListener(newPlayerData.Load);
        }

        void Update()
        {
            playerNameText.text = newPlayerData.PlayerName;
            playerLevelText.text = newPlayerData.Level.ToString();
            playerCoinText.text = newPlayerData.Coin.ToString();
            playerPositionX.text = newPlayerData.Position.x.ToString();
            playerPositionY.text = newPlayerData.Position.y.ToString();
            playerPositionZ.text = newPlayerData.Position.z.ToString();
        }
    }
}

 记得挂载好参数

点击Win+R进入命令行 ,输入以下命令。找到你Unity的目录,

 

当你运行游戏的时候并且输入数据并且保存的时候在你的游戏项目目录里面,就会有注册的新数据,这里我就不演试了,而且当你退出游戏并且重新游戏的时候,你点击Load,之前注册的数据就又会返回了。

简单的数据存储已经实现了,我们还可以删除已经存储的PlayerPrefs,而这个功能Unity已经为我们提供了

    可能你和我会想,一条条的存储和读取数据,这个是否有点。。。。代码的耦合性显而易见的搞。因此我们要创建一个SaveSystem的脚本,并用一个普通的类来实现,我们先把数据转化为文本形式(string类型),然后用PlayerPrefs的SetString像存储键值对一般,再用Save()函数保存,读取则直接返回键以及一个空值

namespace SaveSystemTur
{
    public static  class SaveSystem
    { 
#region PlayerPrefs
        public static void SaveByPlayerPrefs(string key,object data)
        {
            var json = JsonUtility.ToJson(data,true);//true即转化为json的文本格式

            PlayerPrefs.SetString(key, json);
            PlayerPrefs.Save();

#if UNITY_EDITOR
            Debug.Log("成功保存数据到PlayerPrefs");
#endif
        }


        public static string LoadFromPlayerPrefs(string key)
        {
            return PlayerPrefs.GetString(key,null);
        }
        #endregion
     }
}

   我们使用新的扩展方式JsonUtility来实现,通过FromJSON<T>以及ToJSON,我们可以将untiy可以支持的序列化类转化为json格式

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SaveSystemTur
{
    public class NewPlayerData : MonoBehaviour
    {
        private const string PLAYER_DATA_KEY = "PlayerData";

        #region Fields
        [SerializeField] string playerName = "";
        [SerializeField] int coin = 0;
        [SerializeField] int level = 0;

        [System.Serializable]
        class SaveData
        {
            public string playerName;
            public int playerLevel;
            public int playerCoin;
            public Vector3 playerPosition;
        }

        #endregion

        #region Propertries

        public string PlayerName => playerName;
        public int Coin => coin;
        public int Level => level;

        public Vector3 Position => transform.position;
        #endregion

        #region Save And Load
        public void Save()
        {
            SaveByPlayerPrefs();
        }
        public void Load()
        {
            LoadFromPlayerPrefs();
        }

        #region PlayerPrefs

        void SaveByPlayerPrefs()
        {
            SaveData saveData = SavingData();
            SaveSystem.SaveByPlayerPrefs(PLAYER_DATA_KEY, saveData); //把savedata的值存储到键对中
        }

        private SaveData SavingData() //对要存储的数据进行初始化
        {
            var saveData = new SaveData();
            saveData.playerName = playerName;
            saveData.playerCoin = coin;
            saveData.playerLevel = level;
            saveData.playerPosition = transform.position;

            return saveData;
        }

        void LoadFromPlayerPrefs()
        {
            var json = SaveSystem.LoadFromPlayerPrefs(PLAYER_DATA_KEY); //string类型
            var saveData = JsonUtility.FromJson<SaveData>(json); //SaveData类型
            LoadData(saveData); //返回数据给我们所需要保存的数据
        }

        private void LoadData(SaveData saveData)
        {
            playerName = saveData.playerName;
            level = saveData.playerLevel;
            coin = saveData.playerCoin;
            transform.position = saveData.playerPosition;
        }

        #endregion

        #endregion


    }
}

最后因我们有键值对,因此想删除对应的PlayerPrefs找到对应的键即可

在NewPlayerData脚本中

[UnityEditor.MenuItem("Developer/Delete Player Data Prefs")]
        public static void DeletePlayerDataPrefs()
        {
            //PlayerPrefs.DeleteAll();
            PlayerPrefs.DeleteKey(PLAYER_DATA_KEY);
        }

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐