Unity存档系统(使用JsonUtility)

2024-04-09  本文已影响0人  全新的饭

说明

若想存储某对象的数据,则该对象对应的类需继承SaveData。

SaveData提供如下方法:
保存:Save
删除:Delete

静态类SaveSys提供如下方法:
载入某项数据:Load。载入时需传入名称,要求所有要存储的对象不能重名。
存储所有数据:SaveAll
删除所有数据:DeleteAll

使用

  1. 可在游戏开始时Load所有继承自SaveData的数据。
  2. 在合适的时机SaveAll或Save特定数据。
  3. 在合适的时机Delete特定数据。Delete后,需自行调用Destroy方法,重新Load该数据(这次Load的本质是创建新存档)。

具体代码

SaveSys.cs
包含SaveData和SaveSys

using System;
using UnityEngine;

[Serializable]
public abstract class SaveData
{
    public string Name { get; private set; }

    public void Init(string name)
    {
        Destroy();

        Name = name;
        SaveSys.SaveEvent += OnSave;
        SaveSys.DeleteEvent += OnDelete;
        SaveSys.ShowEvent += OnShow;
    }
    public void Destroy()
    {
        SaveSys.SaveEvent -= OnSave;
        SaveSys.DeleteEvent -= OnDelete;
        SaveSys.ShowEvent -= OnShow;
    }

    private void OnSave()
    {
        Save();
    }
    private void OnDelete()
    {
        Delete();
    }
    private void OnShow()
    {
        Debug.Log("存档名称:" + Name);
    }
    public void Save()
    {
        SaveSys.Save(Name, this);
    }
    public void Delete()
    {
        SaveSys.Delete(Name);
    }
}

public static class SaveSys
{
    // 存储所有
    public static event Action SaveEvent;
    // 删除所有
    public static event Action DeleteEvent;
    // 显示名称
    public static event Action ShowEvent;
    private static string NameToPath(string name)
    {
        return Application.persistentDataPath + "/" + name + ".txt";
    }

    public static T Load<T>(string name) where T : SaveData, new()
    {
        var dataStr = string.Empty;
        var path = NameToPath(name);
        if (System.IO.File.Exists(path))
        {
            System.IO.StreamReader file = System.IO.File.OpenText(path);
            dataStr = file.ReadToEnd();
            file.Close();
        }

        T t = null;
        if (dataStr != string.Empty)
        {
            t = JsonUtility.FromJson<T>(dataStr);
        }
        else
        {
            // t = (T)System.Activator.CreateInstance(typeof(T), name);
            t = new T();
            Debug.Log("载入存档数据失败。当前还不存在该存档:" + name + "。创建新存档。");
        }

        t.Init(name);
        t.Save();

        return t;
    }
    public static void Save<T>(string name, T t)
    {
        string content = JsonUtility.ToJson(t, true);
        var path = NameToPath(name);

        if (!System.IO.File.Exists(path))
        {
            // 创建后要主动释放:Dispose
            System.IO.File.CreateText(path).Dispose();
        }
        System.IO.File.WriteAllText(path, content, System.Text.Encoding.UTF8);
        Debug.Log(nameof(SaveSys) + ":保存:" + name);
    }
    public static void Delete(string name)
    {
        var path = NameToPath(name);
        if (System.IO.File.Exists(path))
        {
            System.IO.File.Delete(path);

            Debug.Log("删除:" + name);
        }
    }
    public static void SaveAll()
    {
        SaveEvent?.Invoke();
        Debug.Log(nameof(SaveSys) + ":保存了所有!");
    }
    public static void DeleteAll()
    {
        DeleteEvent?.Invoke();
        Debug.Log(nameof(SaveSys) + ":删除了所有!");
    }
    public static void ShowAll()
    {
        ShowEvent?.Invoke();
        Debug.Log(nameof(SaveSys) + ":如上是所有存档数据!");
    }
}

PlayerData.cs
SaveData的子类,用于测试

using UnityEngine;

public class PlayerData : SaveData
{
    public Vector3 Pos;
}

SaveTest.cs
用于测试

using UnityEngine;

public class SaveTest : MonoBehaviour
{
    private void Start()
    {
        Init();
    }

    private void Update()
    {
        MyUpdate();
    }

    private void OnDestroy()
    {
        MyDestroy();
    }

    private void Init()
    {

    }

    private PlayerData _playerData;
    private PlayerData PlayerData
    {
        get
        {
            _playerData ??= SaveSys.Load<PlayerData>(nameof(PlayerData));
            return _playerData;
        }
    }

    private void MyUpdate()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log("存档中的Player位置:" + PlayerData.Pos);
        }
        else if (Input.GetKeyDown(KeyCode.A))
        {
            SaveSys.ShowAll();
        }
        else if (Input.GetKeyDown(KeyCode.B))
        {
            SaveSys.SaveAll();
        }
        else if (Input.GetKeyDown(KeyCode.C))
        {
            SaveSys.DeleteAll();
        }
        else if (Input.GetKeyDown(KeyCode.D))
        {
            PlayerData.Pos = Vector3.one * UnityEngine.Random.Range(0, 100);
            Debug.Log("修改Player位置:" + PlayerData.Pos);
            PlayerData.Save();
        }
    }

    private void MyDestroy()
    {

    }
}
上一篇下一篇

猜你喜欢

热点阅读