不要破坏加载对象和GameData

时间:2019-11-11 01:21:03

标签: c# json unity3d

我想使用DontDestroyOnLoad对象在2D游戏进行时保存游戏数据。

我有一个GameData类/脚本,用于存储诸如health,magicType等值;一个SaveLoad类/脚本,用于将GameData类中的当前值保存到Json;还有一个空游戏对象,称为{ {1}}具有以上两个脚本。

当前,我通过使用按钮单击事件将值保存在一个场景中。我附加到按钮上的对象是PlayerData对象,我在点击事件上使用PlayerData脚本更改了值。

但这仅适用于第一个场景-我无法附加GameData对象并存储其PlayerData值,因为编辑器中没有PlayerData对象。

那么我该如何附加另一个场景中的对象呢?还是我做错了?

这是我当前项目的照片。 my current project

另外,当我保存一个布尔值,然后打开我的Json文件时,该文件为空。这正常吗?这是我的保存和加载代码:

加载:

GameData

保存:

private string _filePath;
private static DataService _instance;

public DataService Instance
{
    get { return _instance; }
}

public GameData _gameData;

private void Awake()
{
    DontDestroyOnLoad(gameObject);
}

public void LoadGameData()
{
    _filePath = Path.Combine(Application.persistentDataPath, "GameData1.json");
    string json;
    if (File.Exists(_filePath))
    {
        json = File.ReadAllText(_filePath);
        JsonUtility.FromJsonOverwrite(json, _gameData);
    }
    else
    {
        Debug.Log("File missing.");
    }
}

编辑:这是我的GameData类的代码:

public void SaveGameData1()
{
    string json = JsonUtility.ToJson(_gameData);
    _filePath = Path.Combine(Application.persistentDataPath, "GameData1.json");
    if (File.Exists(_filePath))
    {
        File.Create(_filePath).Dispose();
    }
    File.WriteAllText(_filePath,json);
}

1 个答案:

答案 0 :(得分:1)

数据路径

首先,正如最近回答的here,我不会使用persistentDataPath进行开发,而是使用streamingAssetsPath并在首次运行应用程序时将文件复制过来。


单一模式

我看到您具有Singleton模式的前半部但是:您从未为instance分配任何值。我通常会在媒体资源或Awake中将其“懒惰”,例如

private static DataService instance;
public static DataService Instance
{
    if(instance) return instance;

    instance = FindObjectOfType<DataService>();

    if(instance) return instance;

    // If it wasnt found in the scene create it now
    instance = new GameObject("DataService", typeof (GameData)). AddComponent<DataService>();
    instance._gameData = instance.GetComponent<GameData>();

    DontDestroyOnLoad (instance.gameObject);

    return instance;
}

private void Awake ()
{
    if(instance && instance != this)
    {
        Debug.LogWarning("Another instance of DataService I already in use");
        Destroy(gameObject);
        return;
    }

    if(instance) return;

    instance = this;

    DontDestroyOnLoad (gameObject);

    if(!_gameData) _gameData = GetComponent<GameData>();
}

或静态类

实际上,使用您提供的代码,我怀疑您的两个类中的任何一个是否真的都必须是MonoBehaviour

您可能只需使用类似的内容

public static class DataService
{
    private const string FILE_NAME = "GameData1.json";

    public static GameData GameData = new GameData();

    public static void SaveGameData1()
    {
        var json = JsonUtility.ToJson(_gameData);
        var filePath = Path.Combine(Application.persistentDataPath, FILE_NAME);

        if (File.Exists(filePath))
        {
            File.Create(filePath);
        }

        File.WriteAllText(filePath,json);
    }

    public static void LoadGameData()
    {
        var filePath = Path.Combine(Application.persistentDataPath, FILE_NAME);

        if (File.Exists(filePath))
        {
            var json = File.ReadAllText(_filePath);
            JsonUtility.FromJsonOverwrite(json, GameData);
        }
        else
        {
            Debug.Log("File missing.");
        }
    }
}

[Serializable]
public class GameData
{
    public float SomeValue;

    ...
}

现在,您可以随处拨打电话

DataService.LoadGameData();

然后访问值,如

DataService.GameData.SomeValue = ...;

对于按钮

我将创建一个类DataServiceButton,该类将附加到UI.Button上,并像{p>一样注册为onClick的侦听器

[RequireComponent(typeof(UI.Button))]
public class DataServiceButton : MonoBehaviour
{
    public enum ButtonType
    {
        Save,
        Load
    }

    // This is set via the Inspector
    [SerializeField] private ButtonType type;

    // Here you can already reference the according Button component
    [SerializeField] private Button button;

    private void Awake()
    {
        if(!button) button = GetComponent<Button>();

        // Register as callback
        button.onClick.AddListener(HandleClick);
    }

    private void HandleClick()
    {
        switch(type)
        {
            case ButtonType.Load:
                DataService.LoadGameData();
                // OR IF YOU STICK TO THE SINGLETON
                //DataService.Instance.LoadGameData();
                break;
            case ButtonType.Save:
                DataService.SaveGameData();
                // OR ACCORDINGLY WITH SINGLETON
                //DataService.Instance.SaveGameData();
                break;
        }
    }
}

不幸的是,为什么写数据后文件为空的问题在没有看到您的GameData类的代码的情况下无法回答...

确保您的类型可序列化。