8-2. 数据结构及坐标保存加载

使用 ISaveable 标识可保存的数据

现在 C# 也像 Java 一样,接口可以写默认实现。大括号的写法和=>的写法是完全一致的

使用 DataManager 来统一管理所有数据

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

public class DataManager : MonoBehaviour
{
    public static DataManager instance;

    [Header("事件监听")]
    public VoidEventSO saveDataEvent;

    private List<ISaveable> saveableList = new List<ISaveable>();

    private Data saveData;

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
        else
        {
            Destroy(gameObject);
        }

        saveData = new Data();
    }

    private void Update()
    {
        if (Keyboard.current.lKey.wasPressedThisFrame)
        {
            Load();
        }
    }

    private void OnEnable()
    {
        saveDataEvent.OnEventRaised += Save;
    }

    private void OnDisable()
    {
        saveDataEvent.OnEventRaised -= Save;
    }

    public void RegisterSaveData(ISaveable saveable)
    {
        if (!saveableList.Contains(saveable))
        {
            saveableList.Add(saveable);
        }
    }

    public void UnRegisterSaveData(ISaveable saveable)
    {
        saveableList.Remove(saveable);
    }

    public void Save()
    {
        foreach (var saveable in saveableList)
        {
            saveable.GetSaveData(saveData);
        }

        foreach (var item in saveData.characterPosDict)
        {
            Debug.Log($"item.Key = {item.Key}, item.Value = {item.Value}");
        }
    }

    public void Load()
    {
        foreach (var saveable in saveableList)
        {
            saveable.LoadData(saveData);
        }
    }
}

DataManager 使用了单例模式,确保场景中只有一个 DataManager

它里面有个存储结构 Data,Data 里面比较简单,只有一个 Dictionary

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

public class Data
{
    public Dictionary<string, Vector3> characterPosDict = new Dictionary<string, Vector3>();
}

每个 ISaveable 在 enable 的时候,就会把自己添加到 DataManager.saveableList 里面;在 disable 的时候,就会把自己从 DataManager.saveableList 里面删掉

在 Update 里面,DataManager 监听了键盘上的 L 键,当 L 键按下的时候,就会遍历 saveableList,让所有物体回到它们之前记录的坐标

DataManager 监听了 SaveDataEvent,当 SaveDataEvent 产生的时候,DataManager 就会遍历 saveableList,把它们的位置记录下来,并打印一下

需要保存数据的对象继承 ISaveable

注意,每个待保存对象上面都有 DataDefination 组件,代码如下

OnValidate 在编辑器每次修改数据的时候调用一次,为 ID 进行赋值。这个 ID 也是 Data 存储时使用的 Key。

但是这样赋值之后,永远不会变了。我们可能有这样的需求,野猪预制体上面有个 ID,我往场景里添加了四个实例,我希望这四只野猪有不同的 ID,此时就能先把类型切换为 DoNotPersist,然后再切换为 ReadWrite,这样就能实现每只野猪有不同的 ID 了。

继承 ISaveable 的 GetSaveData 方法,就会让 DataManager 把当前物体的坐标记录到 Data 中,LoadData 方法就会让 DataManager 把物体的坐标还原成 Data 中记录的坐标

存储点通知 DataManager 存储数据

现在 DataManager 在监听 saveDataEvent 事件,这个事件由存储点发出

项目相关代码

代码仓库:https://gitee.com/nbda1121440/2DAdventure.git

标签:20240229_1008

posted @ 2024-02-29 10:31  hellozjf  阅读(38)  评论(0编辑  收藏  举报