5.ScriptableObject数据持久化

5.ScriptableObject让其真正意义上的持久


5.1 知识点

回顾通过ScriptableObject创建非持久化数据

MyData myData = ScriptableObject.CreateInstance();

回顾数据持久化

  • 硬盘<=>内存
  • 使用数据时从硬盘中读取
  • 数据改变后保存到硬盘上
  • 游戏退出程序关闭后,数据信息会被存储到硬盘上,达到持久化的目的

我们讲授过的数据持久化相关知识:

  • PlayerPrefs
  • XML
  • Json
  • 2进制

ScriptableObject并不适合用来做数据持久化功能,但是我们可以利用我们学过的数据持久化方案让其持久化。

利用Json结合ScriptableObject存储数据

myData.PrintInfo();

myData.i = 9999;
myData.f = 6.6f;
myData.b = true;

将数据对象序列化为json字符串:

string str = JsonUtility.ToJson(myData);
print(str);

把数据序列化后的结果存入指定路径当中:

File.WriteAllText(Application.persistentDataPath + "/testJson.json", str);
print(Application.persistentDataPath);

利用Json结合ScriptableObject读取数据

从本地读取Json字符串:

str = File.ReadAllText(Application.persistentDataPath + "/testJson.json");

根据json字符串反序列化出数据将内容覆盖到数据对象中:

JsonUtility.FromJsonOverwrite(str, myData);
// FromJsonOverwrite方法是将JSON数据覆盖到现有对象
// FromJson方法JSON数据转换为新的对象实例用一个新对象来接(就算用老对象来接 也是引用新的实例)
myData.PrintInfo();

总结

对于ScriptableObject的数据,由于它在游戏发布运行过程中无法被持久化,我们可以利用PlayerPrefs、XML、Json、2进制等等方式让其可以达到被真正持久化的目的。但是我个人并不建议大家利用ScriptableObject来做数据持久化,有点画蛇添足的意思了。


5.2 知识点代码

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

public class Lesson05_ScriptableObject让其真正意义上的持久 : MonoBehaviour
{
    void Start()
    {
        #region 知识点一 回顾通过ScriptableObject创建非持久化数据
        MyData myData = ScriptableObject.CreateInstance<MyData>();
        #endregion

        #region 知识点二 回顾数据持久化
        //硬盘<=>内存
        //使用数据时从硬盘中读取
        //数据改变后保存到硬盘上
        //游戏退出程序关闭后,数据信息会被存储到硬盘上,达到持久化的目的

        //我们讲授过的数据持久化相关知识
        //PlayerPrefs
        //XML
        //Json
        //2进制

        //ScriptableObject并不适合用来做数据持久化功能
        //但是我们可以利用我们学过的数据持久化方案 让其持久化
        #endregion

        #region 知识点三 利用Json结合ScriptableObject存储数据

        myData.PrintInfo();

        myData.i = 9999;
        myData.f = 6.6f;
        myData.b = true;

        //将数据对象 序列化为 json字符串
        string str = JsonUtility.ToJson(myData);
        print(str);

        //把数据序列化后的结果 存入指定路径当中
        File.WriteAllText(Application.persistentDataPath + "/testJson.json", str);
        print(Application.persistentDataPath);

        #endregion

        #region 知识点四 利用Json结合ScriptableObject读取数据

        //从本地读取 Json字符串
        str = File.ReadAllText(Application.persistentDataPath + "/testJson.json");

        //根据json字符串反序列化出数据 将内容覆盖到数据对象中 
        JsonUtility.FromJsonOverwrite(str, myData);
        //FromJsonOverwrite方法是将JSON数据覆盖到现有对象
        //FromJson方法JSON数据转换为新的对象实例 用一个新对象来接(就算用老对象来接 也是引用新的实例)
        myData.PrintInfo();
        #endregion

        #region 总结
        //对于ScriptableObject的数据
        //由于它在游戏发布运行过程中无法被持久化
        //我们可以利用 PlayerPrefs、XML、Json、2进制等等方式
        //让其可以达到被真正持久化的目的

        //但是我个人并不建议大家利用ScriptableObject来做数据持久化
        //有点画蛇添足的意思了
        #endregion
    }
}

5.3 练习题

请在上节课的练习题基础上,把不持久化数据持久化,可以记录下相关信息,下次启动时能够记录上次设置的内容

在继承ScriptableObject的SettingInfo脚本中;Awake初始化的时候判断持久化路径下有没有存储的数据文件,有点话进行读取;添加一个保存本地的方法,保存当前数据到持久化路径中

private void Awake()
{
    //判断是否存在持久化的数据文件
    if( File.Exists(Application.persistentDataPath + "/SettingInfo.json") )
    {
        string str = File.ReadAllText(Application.persistentDataPath + "/SettingInfo.json");
        JsonUtility.FromJsonOverwrite(str, this);
    }
}

/// <summary>
/// 保存到本地 进行持久化
/// </summary>
public void Save()
{
    string str = JsonUtility.ToJson(this);
    File.WriteAllText(Application.persistentDataPath + "/SettingInfo.json", str);
}

在SettingPanel脚本中添加按下空格键保存的逻辑

void Update()
{
    // 当按下空格键时保存设置信息
    if (Input.GetKeyDown(KeyCode.Space))
        settingInfo.Save();
}

尝试发布后可以测试出数据被真正持久化了


5.4 练习题代码

SettingPanel

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

public class SettingPanel : MonoBehaviour
{
    public Toggle musicTog; // 音乐开关
    public Toggle soundTog; // 音效开关
    public Slider musicSlider; // 音乐滑动条
    public Slider soundSlider; // 音效滑动条

    public SettingInfo settingInfo; // 设置信息

    void Start()
    {
        // 创建设置信息实例
        settingInfo = ScriptableObject.CreateInstance<SettingInfo>();

        // 将设置信息应用到UI控件上
        musicTog.isOn = settingInfo.musicIsOpen;
        soundTog.isOn = settingInfo.soundIsOpen;
        musicSlider.value = settingInfo.musicValue;
        soundSlider.value = settingInfo.soundValue;

        // 当音乐开关控件值发生变化时,记录修改后的值到设置信息中
        musicTog.onValueChanged.AddListener((value) =>
        {
            settingInfo.musicIsOpen = value;
        });

        // 当音效开关控件值发生变化时,记录修改后的值到设置信息中
        soundTog.onValueChanged.AddListener((value) =>
        {
            settingInfo.soundIsOpen = value;
        });

        // 当音乐滑动条控件值发生变化时,记录修改后的值到设置信息中
        musicSlider.onValueChanged.AddListener((value) =>
        {
            settingInfo.musicValue = value;
        });

        // 当音效滑动条控件值发生变化时,记录修改后的值到设置信息中
        soundSlider.onValueChanged.AddListener((value) =>
        {
            settingInfo.soundValue = value;
        });
    }

    void Update()
    {
        // 当按下空格键时保存设置信息
        if (Input.GetKeyDown(KeyCode.Space))
            settingInfo.Save();
    }
}

SettingInfo

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

[CreateAssetMenu(fileName = "SettingInfo", menuName = "ScriptableObject/音乐音效设置信息")]
public class SettingInfo : ScriptableObject
{
    //音乐和音效的开关
    public bool musicIsOpen;
    public bool soundIsOpen;

    //音乐和音效的 大小
    public float musicValue;
    public float soundValue;

    private void Awake()
    {
        //判断是否存在持久化的数据文件
        if (File.Exists(Application.persistentDataPath + "/SettingInfo.json"))
        {
            string str = File.ReadAllText(Application.persistentDataPath + "/SettingInfo.json");
            JsonUtility.FromJsonOverwrite(str, this);
        }
    }

    /// <summary>
    /// 保存到本地 进行持久化
    /// </summary>
    public void Save()
    {
        string str = JsonUtility.ToJson(this);
        File.WriteAllText(Application.persistentDataPath + "/SettingInfo.json", str);
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏