Сначала вы должны взглянуть на Сериализация 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
, который в любом случае уже сериализуем.