- Home /
Serializing subclass of generic class not working
I'm trying to serialize a generic class by creating special subclasses as mentioned in many placed (even the documentation for UnityEvent) but it's not working as expected.
[Serializable]
public class SceneData
{
// Need to create subclasses to be able to serialize
[Serializable]
private class PersistentBoolCollection : PersistentItemDataCollection<bool> { }
[SerializeField]
private PersistentBoolCollection persistentBools;
}
[Serializable]
public class PersistentItemDataCollection<T> : ISerializationCallbackReceiver
where T : struct
{
// Use special data type for serialization
[Serializable]
private struct SerializableItemData
{
public string SceneName;
public string ID;
public T Value;
}
[SerializeField]
private List<SerializableItemData> serializedList = new List<SerializableItemData>();
[NonSerialized]
private Dictionary<string, Dictionary<string, PersistentItemData<T>>> scenes
= new Dictionary<string, Dictionary<string, PersistentItemData<T>>>();
public void OnAfterDeserialize()
{
// Convert itemData to dictionary for fast runtime access
scenes = new Dictionary<string, Dictionary<string, PersistentItemData<T>>>(serializedList.Count);
foreach (var serializableItem in serializedList)
{
scenes[serializableItem.SceneName][serializableItem.ID] = new PersistentItemData<T>
{
SceneName = serializableItem.SceneName,
ID = serializableItem.ID,
Value = serializableItem.Value
};
}
}
public void OnBeforeSerialize()
{
// Dictionaries can't be serialized so convert to list first
serializedList = new List<SerializableItemData>();
foreach (var scene in scenes)
{
foreach (var id in scene.Value)
{
serializedList.Add(new SerializableItemData
{
SceneName = scene.Key,
ID = id.Key,
Value = id.Value.Value
});
}
}
}
public void SetValue(PersistentItemData<T> itemData)
{
if (!scenes.ContainsKey(itemData.SceneName))
scenes[itemData.SceneName] = new Dictionary<string, PersistentItemData<T>>();
scenes[itemData.SceneName][itemData.ID] = itemData;
}
public bool TryGetValue(string sceneName, string id, out PersistentItemData<T> value)
{
if (scenes.ContainsKey(sceneName) && scenes[sceneName].ContainsKey(id))
{
value = scenes[sceneName][id];
return true;
}
else
{
value = default(PersistentItemData<T>);
return false;
}
}
}
When using JsonUtility to serialize SceneData the output is:
"sceneData":{"persistentBools":{},"persistentInts":{}}
I confirmed that there were 24 items in the list after the OnBeforeSerialize callback, so I'm not sure what is going wrong here.
Answer by Jackv949 · Sep 25, 2018 at 08:11 AM
Turns out Unity will only serialize generic types that are one level deep. It's not ideal, but a workaround is to make the subclass another public class and pass it in:
[Serializable]
public class SerializableItemData<T>
{
public string SceneName;
public string ID;
public T Value;
}
[Serializable]
public class PersistentItemDataCollection<T, U> : ISerializationCallbackReceiver
where T : struct
where U : SerializableItemData<T>, new()
{
[SerializeField]
private List<U> serializedList = new List<U>();
[NonSerialized]
private Dictionary<string, Dictionary<string, PersistentItemData<T>>> scenes
= new Dictionary<string, Dictionary<string, PersistentItemData<T>>>();
}
And then use it like so:
[Serializable] public class SerializableBoolData : SerializableItemData<bool> { }
[Serializable] private class PersistentBoolCollection : PersistentItemDataCollection<bool, SerializableBoolData> { }
[Serializable] public class SerializableIntData : SerializableItemData<int> { }
[Serializable] private class PersistentIntCollection : PersistentItemDataCollection<int, SerializableIntData> { }
#endregion
[SerializeField]
private PersistentBoolCollection persistentBools;
public PersistentItemDataCollection<bool, SerializableBoolData> PersistentBools { get { return persistentBools; } }
[SerializeField]
private PersistentIntCollection persistentInts;
public PersistentItemDataCollection<int, SerializableIntData> PersistentInts { get { return persistentInts; } }
Your answer
Follow this Question
Related Questions
How to protect JSON file game data? 3 Answers
Is it possible to executing object serialization into JSON asynchronously? 1 Answer
JsonUtility array not supported? 7 Answers
How to serialize parameters from JSON? 1 Answer
Multiple Cars not working 1 Answer