如何添加新数据并保留旧的现有数据

时间:2019-01-08 10:01:03

标签: c# unity3d

我几乎完成了手机游戏的制作,并且我有一个使用this视频中显示的内容的DATA脚本。我有一个列表,其中包含玩家可以完成的各种挑战的值。我将如何更新游戏,以便在保留旧数据的同时增加更多挑战。

(挑战数据基本上包含它是否已经完成以及完成的距离有多远)

我看过this指南,但我不太理解。我是序列化的新手。

预先感谢您:)

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

[System.Serializable]
public class XMLManager : MonoBehaviour {

    public static XMLManager dataManagement;

    public gameData data;


    void Awake()
    {
        //File.Delete(Application.dataPath + "/StreamingFiles/XML/item_data.xml");
        System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
        dataManagement = this;
        DontDestroyOnLoad(gameObject);

    }


    public void SaveData()
    {
        XmlSerializer serializer = new XmlSerializer(typeof(gameData));
        System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
        FileStream stream = new FileStream(Application.dataPath + "/StreamingFiles/XML/item_data.xml", FileMode.Create);
        serializer.Serialize(stream, data);
        stream.Close();
    }
    public void LoadData()
    {
        System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");
        if (File.Exists(Application.dataPath + "/StreamingFiles/XML/item_data.xml"))
        {
            XmlSerializer serializer = new XmlSerializer(typeof(gameData));
            FileStream stream = new FileStream(Application.dataPath + "/StreamingFiles/XML/item_data.xml", FileMode.Open);
            data = serializer.Deserialize(stream) as gameData;
            stream.Close();

        }
        else
        {
            print("SaveData");
            SaveData();
        }


    }
}

[System.Serializable]
public class gameData
{


    public List<ChallengeStatus> Challenges;
    public int HighScore;
    public int CoinsCollected;
    public List<bool> Unlocked;
    public int GamesPlayed;
    public int currentChallenge;

}
[System.Serializable]
public class ChallengeStatus
{


    public int id;
    public string title;
    public int current;
    public int max;
    public int reward;
    public bool completed;
    public bool claimed;



}

1 个答案:

答案 0 :(得分:0)

首先,您应该查看Unity XML Serialization并使用适当的属性。您并非完全不需要它们(也许[XmlRoot]除外),但是它们使您可以自定义Xml文件。如果未提供,Unity将使用变量名称,并使用子元素而不是属性。但是,afaik仅适用于原语(intfloatstringbool等),并且不适用于您自己的类ChallengeStatus。因此,至少对于您的课程列表,您必须提供属性:

[System.Serializable]
[XmlRoot("GameData")]
public class GameData
{
    [XmlArray("Challenges")]
    [XmlArrayItem("ChallengeStatus)]
    public List<ChallengeStatus> Challenges;

    //...
}

现在我不太明白为什么保存新的XML文件时需要保留旧的XML文件,但是如果要保留当前的文件,我会添加int FileCounter ..当然不是使用相同的XML文件;)可能是例如通过PlayerPrefs或另一个仅包含数字或类似内容的简单文本文件。

请注意,最好使用Path.Combine来连接系统路径)-重载采用字符串数组需要.Net4。像

private string FilePath 
{
    get
    {
        //TODO first load / read the FileCounter from somewhere

        var paths = {
        Application.dataPath, 
        "StreamingFiles", 
        "XML", 

        // here you get from somewhere and use that global FileCounter
        string.Format("item_data_{0}.xml", FileCounter)};

        return Path.Combine(paths);
    }
}

每次您保存文件时,都可以增加全局FileCounter

public void SaveData()
{
    //TODO somehow increase the global value
    // store to PlayerPrefs or write a new file or ...
    FileCounter += 1;

    System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");   

    // better use the "using" keyword for streams
    // use the FilePath field to get the filepath including the filecounter
    using(FileStream stream = new FileStream(FilePath, FileMode.Create))
    {
        XmlSerializer serializer = new XmlSerializer(typeof(gameData))
        serializer.Serialize(stream, data);
    }
}

并使用当前的FileCounter读取文件而无需增加文件

public void LoadData()
{
    System.Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");

    if (File.Exists(FilePath))
    {
        // better use a "using" block for streams
        // use the FilePath field to get the filepath including the filecounter
        using(FileStream stream = new FileStream(FilePath, FileMode.Open))
        {
            XmlSerializer serializer = new XmlSerializer(typeof(gameData));
            data = serializer.Deserialize(stream) as gameData;
        }
    }
    else
    {
        print("SaveData");
        SaveData();
    }
}

提示1
一旦为您的类提供了构造函数,例如

public GameData(List<ChallengeStatus> challenges)
{
    Challenges = challenges;
}

比您总是还要提供一个默认的构造函数(即使它什么也不做)

public GameData(){ }

提示2:
您应该始终初始化列表:

public class GameData
{
    public List<ChallengeStatus> Challenges = new List≤ChallangeStatus>();
    //...

    public List<bool> Unlocked = new List<bool>();

    //...
}

提示3
顺便说一句,您不需要[System.Serializable]的{​​{1}},因为它是从XmlManager继承的,而该MonoBehaviour已经可以序列化了。