Как добавить новые данные и сохранить старые существующие данные - PullRequest
0 голосов
/ 08 января 2019

Я почти закончил делать свою мобильную игру, и у меня есть сценарий DATA, использующий то, что показано в этом видео. У меня есть список, содержащий значения различных задач, которые игрок может выполнить. Как бы я обновил игру, чтобы я мог добавлять больше задач, сохраняя при этом старые данные.

(Данные по заданию в основном содержат информацию о том, была ли она завершена и насколько она завершена)

Я посмотрел это руководство, но я не совсем понимаю его. Я новичок в сериализации.

Заранее спасибо:)

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 голосов
/ 11 января 2019

Сначала вы должны взглянуть на Сериализация XML Unity и использовать надлежащие атрибуты. Вам они не нужны полностью (за исключением, может быть, [XmlRoot]), но они позволяют вам настраивать ваш файл XML. Если не указано иное, Unity использует имена переменных и использует подэлементы вместо атрибутов. Однако это работает только для примитивов (int, float, string, bool и т. Д.) И их списки не для вашего собственного класса ChallengeStatus. Поэтому, по крайней мере, для списка вашего класса вы должны предоставить атрибуты:

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

    //...
}

Теперь я не совсем понимаю, зачем вам сохранять старый 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] для XmlManager, поскольку оно наследуется от MonoBehaviour, который в любом случае уже сериализуем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...