Skip to content

Instantly share code, notes, and snippets.

@SradnickDev
Last active June 24, 2020 21:09
Show Gist options
  • Save SradnickDev/f11e340d5f7f2e4d780829f8c61c0d16 to your computer and use it in GitHub Desktop.
Save SradnickDev/f11e340d5f7f2e4d780829f8c61c0d16 to your computer and use it in GitHub Desktop.
SerializedScriptableObject allows to serialize stuff that unity cant like, inheritance for custom classes in e.g in lists. With the use of https://www.newtonsoft.com/json
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
namespace Core.Utilities
{
/// <summary>
/// To extend Unity's serialization process.
/// Unity cant serializes inheritance properly e.g in a list of base types, adding an inherited class won’t be serialized as it.
/// This uses ISerializationCallbackReceiver to inject custom serialization within the default process.
/// Using a list to add/read JSON data that then is serialized/deserialization by unity.
/// Unity's JsonUtility isn't capable of managing inheritance, but Newtonsoft.Json is without changing the default unity workflow.
/// </summary>
public abstract class SerializedScriptableObject : ScriptableObject,
ISerializationCallbackReceiver
{
/// <summary>
/// Container for json data.
/// </summary>
[SerializeField, HideInInspector]
private List<string> m_serializeData = new List<string>();
[NonSerialized]
private int m_index;
private bool m_isSerializing;
//Newtonsoft don't write type information by default, we have to use settings for this
private JsonSerializerSettings m_settings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All,
};
/// <summary>
/// Can be used to serialize custom data to json.
/// <remarks>
/// Don't forget to use the [Serializable]/[SerializeField]/[NonSerialized] Attribute to work properly.
/// </remarks>
/// </summary>
/// <param name="data">Object that should be serialized.</param>
/// <typeparam name="T">Type information of the target object.</typeparam>
protected void Serialize<T>(T data)
{
var result = JsonConvert.SerializeObject(data, m_settings);
m_serializeData.Add(result);
}
/// <summary>
/// Can be used to deserialize custom data from json.
/// <remarks>
/// Don't forget to Deserialize in the same order as you serialize.
/// </remarks>
/// </summary>
/// <typeparam name="T">Type information of the target object.</typeparam>
protected T Deserialize<T>()
{
var data = m_serializeData[m_index];
m_index++;
return JsonConvert.DeserializeObject<T>(data, m_settings);
}
/// <summary>
/// Used to implement custom serialization
/// </summary>
public abstract void OnSerialize();
/// <summary>
/// Used to implement custom deserialization
/// </summary>
public abstract void OnDeserialize();
/// <summary>
/// Unity callback
/// </summary>
public void OnBeforeSerialize()
{
m_isSerializing = true;
m_serializeData = new List<string>();
OnSerialize();
m_isSerializing = false;
}
/// <summary>
/// Unity callback
/// </summary>
public void OnAfterDeserialize()
{
if (m_isSerializing)
{
m_index = 0;
OnDeserialize();
}
}
}
}
@SradnickDev
Copy link
Author

Example

public class Fruit{}
public class Apple : Fruit{}
public class Banana : Fruit{}
public class FruitTable : SerializedScriptableObject
{
	public List<Fruit> Fruits = new List<Fruit>()
	{
		new Apple(),
		new Banana(),
		new Apple(),
		new Banana(),
	};

	public override void OnSerialize()
	{
		Serialize(Fruits);
	}

	public override void OnDeserialize()
	{
		Fruits = Deserialize<List<Fruit>>();
	}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment