Unity日记20(存档读档PlayerPrefs和PlayerPrefs拓展)

时间:2023-04-07 08:03:05

资源来源:[Unity] 存档系统 Part 1 | PlayerPrefs | Unity初学者系列教程 | 数据存取 | 存档读档 | Save&Load_哔哩哔哩_bilibili


目录

1.PlayerPrefs

优缺点

      适用于

示例

1.创建UI界面

        2.编写玩家数据类和UI控制类的脚本

3.添加脚本

 4.测试方法

2.Json-PlayerPrefs

和1相比

用法

流程运作:

        示例

体会

1.=》使用

2.暴露变量“标题”和“项”

 3.Unity编辑界面菜单功能设计

4.序列化SerializeField和public的区别


 

1.PlayerPrefs

Unity引擎内建主要用来存储玩家偏好的类。

优缺点

优点:简单,容易使用

缺点:

1.存储复杂数据困难

2.存储数据类型有限

适用于

暂时性数据

玩家偏好

示例

Unity日记20(存档读档PlayerPrefs和PlayerPrefs拓展)

在检查器中修改玩家数据的暴露变量后。点击保存,存储当前文本框的信息。

重启游戏。点击读档,读取上次保存的信息。

1.创建UI界面

文本框、按钮、背景图

Unity日记20(存档读档PlayerPrefs和PlayerPrefs拓展)

2.编写玩家数据类和UI控制类的脚本

玩家数据类

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

public class PlayerData : MonoBehaviour
{
    #region Fields
    //用户名
    [SerializeField] string PlayerName = "斯卡蒂000";
    //等级
    [SerializeField] int PlayerLevel = 300;
    //金币
    [SerializeField] int PlayerCoins = 2000;
    #endregion

    #region Properties
    public string Name => PlayerName;
    public int level => PlayerLevel;
    public int Coin => PlayerCoins;
    public Vector3 Position => transform.position;
    #endregion

    public void Save() {
        SaveByPlayerPrefs();
    }
    public void Load() {
        LoadFromPlayerFrefs();
    }

    void SaveByPlayerPrefs()
    {
        PlayerPrefs.SetString("PlayerName", PlayerName);
        PlayerPrefs.SetInt("PlayerLevel", PlayerLevel);
        PlayerPrefs.SetInt("PlayerCoins", PlayerCoins);
    }
    void LoadFromPlayerFrefs()
    {
        PlayerName = PlayerPrefs.GetString("PlayerName");
        PlayerLevel = PlayerPrefs.GetInt("PlayerLevel");
        PlayerCoins = PlayerPrefs.GetInt("PlayerCoins");
    }
}

UI控制类

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

public class UIControler : MonoBehaviour
{
    [Header("-Texts-")]
    [SerializeField] Text PlayerNameText;
    [SerializeField] Text PlayerLevelText;
    [SerializeField] Text PlayerCoinText;
    [SerializeField] Text PlayerPositionText_X;

    [Header("-Button-")]
    [SerializeField] Button buttonSave;
    [SerializeField] Button buttonLoad;

    
    [Header("-PLayer Data-")]
    //用户数据类
    [SerializeField] PlayerData playerData;


    void Start()
    {
        //点击按钮直接调用后面的方法
        buttonSave.onClick.AddListener(() => playerData.Save());

        buttonLoad.onClick.AddListener(() => playerData.Load());
    }

    // Update is called once per frame
    void Update()
    {
        PlayerNameText.text = playerData.Name;
        PlayerLevelText.text = playerData.level.ToString();
        PlayerCoinText.text = playerData.Coin.ToString();
        PlayerPositionText_X.text = playerData.Position.x.ToString("0.00");

    }
}

3.添加脚本

添加一个空物体用来实例化玩家数据类脚本,并将UI控制类脚本挂载到UI画布上。

Unity日记20(存档读档PlayerPrefs和PlayerPrefs拓展)

Unity日记20(存档读档PlayerPrefs和PlayerPrefs拓展)

 4.测试方法

在空对象挂载的玩家数据中 ,修改暴露变量的值,点击Game界面的保存。重启游戏,点击读档,即可看到画面显示的是修改后的值。(数据在点击保存后存储到了注册表中。)

Unity日记20(存档读档PlayerPrefs和PlayerPrefs拓展)


2.Json-PlayerPrefs

和1相比

引入了json的概念。作为PlayerPrefs的拓展。

用法

在PlayerPrefs使用示例的基础上新增一个静态类savesystem。

静态类savesystem功能有三:

1.保存

2.读档

3.删档

PlayerData类中,复制了一遍玩家的基本信息,称savedata类。作为json数据传输用。

Unity日记20(存档读档PlayerPrefs和PlayerPrefs拓展)

该类在声明时需要添加(下)

[System.Serializable]

作用:与json序列化和反序列化,解析有关。 

(114条消息) Unity中[System.Serializable]作用-CSDN博客

流程运作:

保存:

1.UI控制器类监听到用户有保存数据操作,会调用PlayerData类的使用存储函数SaveByPlayerPrefs。

2.存储函数SaveByPlayerPrefs会临时new一个json传输类savedata,将要存储的信息装到savedata里面。

2.
        var p = new SaveData();
       p.PlayerName = PlayerName;
        p.PlayerLevel = PlayerLevel;
        p.PlayerCoins = PlayerCoins;
        p.PlayPosition = Position;
        SaveSystem.SaveByPlayerPrefs(KEY_PLAYER_DATA, p);

3.再将savedata传输给静态类SaveSystem的SaveByPlayerPrefs方法,该方法会用JsonUtility.ToJson将savedata转换为json(var接收转换后结果)。

4.PlayerPrefs.SetString(键值,var)存储。

(5.键值是自己设计的常量)

读档:

1.UI控制器类监听到用户读档数据,调用PlayerData类的使用读档函数(LoadFromPlayerFrefs)。

2.读档函数通过键值从静态类SaveSystem的LoadFromPlayerPrefs中获取数据。

3.利用var接收获取数据的结果(因为存储的是json,所以返回的是json)。将var反转换成类。

        var json= SaveSystem.LoadFromPlayerPrefs(KEY_PLAYER_DATA);
        var mes = JsonUtility.FromJson<SaveData>(json);

4.PlayerData的值重新赋值一遍。因为UI控制类的玩家数据的刷新操作是每帧,所以读档操作会以极快的速度显示出来。

示例

使用方法无改变

UI控制类无改变

玩家数据类

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

public class PlayerData : MonoBehaviour
{
    private const string KEY_PLAYER_DATA = "Key_PlayerData";
    #region Fields
    //用户名
    [SerializeField] string PlayerName = "斯卡蒂000";
    //等级
    [SerializeField] int PlayerLevel = 300;
    //金币
    [SerializeField] int PlayerCoins = 2000;
    #endregion
    [System.Serializable]class SaveData
    {
        public string PlayerName;
        public int PlayerLevel;
        public int PlayerCoins;
        public Vector3 PlayPosition;
    }
    #region Properties
    public string Name => PlayerName;
    public int level => PlayerLevel;
    public int Coin => PlayerCoins;
    public Vector3 Position => transform.position;
    #endregion

    public void Save() {
        SaveByPlayerPrefs();
    }
    public void Load() {
        LoadFromPlayerFrefs();
    }

    void SaveByPlayerPrefs()
    {
        /* PlayerPrefs.SetString("PlayerName", PlayerName);
         PlayerPrefs.SetInt("PlayerLevel", PlayerLevel);
         PlayerPrefs.SetInt("PlayerCoins", PlayerCoins);*/
        var p = new SaveData();
       p.PlayerName = PlayerName;
        p.PlayerLevel = PlayerLevel;
        p.PlayerCoins = PlayerCoins;
        p.PlayPosition = Position;
        SaveSystem.SaveByPlayerPrefs(KEY_PLAYER_DATA, p);

    }
    void LoadFromPlayerFrefs()
    {
        /*PlayerName = PlayerPrefs.GetString("PlayerName");
        PlayerLevel = PlayerPrefs.GetInt("PlayerLevel");
        PlayerCoins = PlayerPrefs.GetInt("PlayerCoins");*/
        var json= SaveSystem.LoadFromPlayerPrefs(KEY_PLAYER_DATA);
        var mes = JsonUtility.FromJson<SaveData>(json);
        PlayerName = mes.PlayerName;
        PlayerLevel = mes.PlayerLevel;
        PlayerCoins = mes.PlayerCoins;
        transform.position = mes.PlayPosition;
    }
}

静态类savesystem

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

public static class SaveSystem//静态类 
{
    public static void SaveByPlayerPrefs(string key,object data)
    {
        var json = JsonUtility.ToJson(data);//数据转json类型
        PlayerPrefs.SetString(key, json);
        PlayerPrefs.Save();

    }

    public static string LoadFromPlayerPrefs(string key)
    {
        return PlayerPrefs.GetString(key,null);
    }
    [UnityEditor.MenuItem("GAME——SAVE/游戏存档相关")]//静态函数才能生效
    public static void DeletePlayerPrefs()
    {
        PlayerPrefs.DeleteAll();
        //PlayerPrefs.DeleteKey("xxx");删除指定键
    }
}

体会

1.=》使用

1.按钮按下调用可以调用跨类的方法,很好用,更简便

        //点击按钮直接调用后面的方法
        buttonSave.onClick.AddListener(() => playerData.Save());

2.赋值,将后面赋值给前面

每次调用Position会执行返回transform.position的操作。(get操作)


    public Vector3 Position => transform.position;

2.暴露变量“标题”和“项”

Header 标头

SerializeField 序列化字段

    [Header("-Texts-")]
    [SerializeField] Text PlayerNameText;

 Unity日记20(存档读档PlayerPrefs和PlayerPrefs拓展)

 3.Unity编辑界面菜单功能设计

Unity日记20(存档读档PlayerPrefs和PlayerPrefs拓展)

前提:调用的函数为静态函数

样式:

 [UnityEditor.MenuItem("GAME——SAVE/游戏存档相关")]//静态函数才能生效
    public static void DeletePlayerPrefs()
    {
        PlayerPrefs.DeleteAll();
        //PlayerPrefs.DeleteKey("xxx");删除指定键
    }

 “/”左边是功能栏,右边是下拉菜单的功能。

4.序列化SerializeField和public的区别

public看不到private,而SerializeField能在检查器中看到。

(114条消息) Unity3D中Public和[SerializeField]的使用_public serializefiel_conjee.的博客-CSDN博客