#Save/Load system parsing issue
1 messages · Page 1 of 1 (latest)
Think it was about time I made this a thread
Original issue link: #archived-code-general message
which part are you interested in?
here is the load:
public static SaveData Load()
{
string fullPath = Application.persistentDataPath + directory + fileName;
if(File.Exists(fullPath))
{
string json = File.ReadAllText(fullPath);
SaveData data = JsonConvert.DeserializeObject<SaveData>(json);
List<UniqueID> uniqueIDs = Object.FindObjectsByType<UniqueID>(FindObjectsSortMode.None).ToList();
foreach(var kvp in data.idToSaveableItems)
uniqueIDs.Find(x => x.ID.Equals(kvp.Key)).GetComponent<ISaveable>().LoadData(kvp.Value);
OnLoadGame?.Invoke(data);
}
else
{
Debug.Log("File doesn't exist");
}
return null;
}
And the Save data object?
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class SaveData
{
public SerializableDictionary<string, Data> idToSaveableItems = new SerializableDictionary<string, Data>();
public SaveData()
{
UnityEngine.Object.FindObjectsByType(typeof(GameObject), FindObjectsSortMode.None)
.ToList()
.Where(x => ((GameObject)x).GetComponent<ISaveable>() != null)
.ToList()
.ForEach(saveable =>
{
string id = ((GameObject)saveable).GetComponent<UniqueID>().ID;
idToSaveableItems.Add(id, ((GameObject)saveable).GetComponent<ISaveable>().GetData());
});
}
}
whoops forget abt the bottom part im not using that anymore
What sata is missing? The json seems to have two entries and so does data after deserializing?
Sorry, I'm on a phone right now so it's hard to read
well the data is there in the file: {"idToSaveableItems":{"08c14717-39a1-4a49-86e4-0d8e4641ded8":{"value":66789},"93f53778-351b-44de-b203-5f8ee2e3f5f4":{"value":1423}}}
but when it converts it to the SaveData object the value is not accessible. Or maybe I am doing something wrong. Here's how I am trying to get it
public void LoadData(Data dataContainer)
{
print("Loading! " + gameObject.name + ": " + value);
value = ((CoinData)dataContainer).value;
print("Loaded! " + gameObject.name + ": " + value);
}
which obviously the error is with the cast
as for this it is the value that is missing when converting back to SaveData
you can see there is 2 Data objects but they don't have values
im beginning to think this isnt possible
Would the behaviour change if you changed the idToSaveableItems field to a property?
I have never seen this error befor, nor have I seen this class in general
That being SerializableDictionary
If the point is the ability to serialize a Dictionary, then note that newtonsoft can serialize Dictionaries without the need of special classes. Maybe just using a Dictionary works here
I assume you have this because JSONUtility might work with it, one of the many requirements to serialize in general
Wow wait really
Wasn’t aware of that. Im running errands right now but when I am home I will try just using a regular dictionary as well as making it a property
I will report back with the results 🙏
And just to clarify should the casting work with this setup? Assuming it does retrieve the data
A little late and I have to run, but what I was looking into last night was the TypeNameHandling option, specifically the Auto or All values. These serialize the the fully qualified type name along with the data, so it's possible to both serialize and deserialize your classes without explicit typing or casting!
(Edit: though, if you heed the remarks and write validation for the types prior to deserialization to prevent users from modifying the JSON to instantiate whatever type, you may still end up with the deserialization logic having some sort of explicit knowledge of the types)
The more I've thought about it, the more I think explicit typing makes sense... but serializing the type is an interesting possibility that could be fun to play with. Especially if users potentially doing weird stuff with the JSON files isn't a concern 👍
This was the answer, I added the JsonSerializerSettings with the TypeNameHandling to Auto and it worked immediately after adding that. very cool that it works like that. I am going to continue experimenting, as I don't love the fact that the type names are editable... ill probably convert it to binary as well, but i would still prefer a way to make this happen without serializing the types. Although the more I think about it I am not sure how you could know the derived classes without serializing it...
However another thought is that if they can edit the json to begin with then you have already lost
cc @clear crane
Just FYI when trying to serialize structs Newtonsoft has some issues, after I applied the ReferenceLoopHandling = ReferenceLoopHandling.Ignore property all is well again
here are the blocks.
Save:
string json = JsonConvert.SerializeObject(data, Formatting.Indented, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto,
});
Load:
SaveData data = JsonConvert.DeserializeObject<SaveData>(json, new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto,
});
If you were curious! Thanks for the help, both of you!
Is this because you try to serialize a Vector3 for example?
Unity types are very poorly written for serializers that are not JSONUtility. It is fixable but they never did
You can work around it by having a custom profile for these types instead. It would be a better fix than ignoring loops like that. There are examples online
Yes. Its because you can do stuff like vector.normalized.normalized.normalized….