Я использую JSON.net в Unity для сохранения игровых данных. Я создал класс Savegame, который содержит все данные, которые я хочу сохранить. Допустим, я получил список персонажей и объект Player, который содержит ссылку на один из этих персонажей. Используя PreserveReferencesHandling, результирующий JSON выглядит ожидаемым образом:
{
"characters":[
{
"$id": "1",
"name": "char1",
"reputation": 100
},
...
"player": {
"location": "town1",
"character": {
"$ref": "1"
}
}
}
Когда я десериализирую Savegame, список персонажей и проигрыватель восстанавливаются и устанавливается ссылка на персонажа. Теперь я мог назначить объект Player из Savegame обратно объекту Player в моем GameManager, где Player используется на протяжении всей игры.
Итак, вкратце: на GameManager.Player ссылается Savegame, который затем сериализуется. После загрузки нового игрока с сохраненными данными в Savegame создается и Savegame.Player присваивается GameManager.Player.
Проблема в том, что каждая часть игры, которая имела ссылку на GameManager.Player, теперьвсе еще ссылаются на старый объект Player, в то время как GameManager.Player теперь содержит новую ссылку на вновь созданного Player (надеюсь, что это имеет смысл).
Так что я мог убедиться, что ссылки на Player не кэшируютсячто я пытаюсь сделать, я мог бы заполнить существующий проигрыватель данными из Savegame. JSON.net предоставляет метод для этого с именем JsonConvert.PopulateObject(string value, object target)
. Поэтому я проанализировал JSON и вытащил проигрыватель из него, но заполнение персонажа внутри проигрывателя оказалось не очень успешным, потому что в этой части JSON была только ссылка без данных.
Поэтому мой вопрос: какзаполнить объекты этими ссылками при извлечении их из всего контекста?
Упрощенные фрагменты кода ниже.
public class GameManager{
public static GameManager instance; //singleton
public List<Character> characters;
public Player player; //<-- other classes may have a ref to this
//...
}
public class Character{
public string name;
public int reputation;
//...
}
public class Player{
public string location;
public Character character;
//...
}
public class Savegame{
public List<Character> characters;
public Player player;
public Savegame(){
characters=GameManager.instance.characters;
player=GameManager.instance.player;
}
public static void Save(){
string saveJson = JsonConvert.SerializeObject(new Savegame(), Formatting.Indented,
new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
string dest = Path.Combine(Application.persistentDataPath, "gmSave.json");
File.WriteAllText(dest, saveJson);
}
public static void Load(){
string dest = Path.Combine(Application.persistentDataPath, "gmSave.json");
string saveJson = File.ReadAllText(dest);
Savegame savegame = JsonConvert.DeserializeObject<Savegame>(saveJson);
JObject jo = JObject.Parse(saveJson);
JsonConvert.PopulateObject(jo["player"].ToString(), GameManager.instance.player);
}
}