Does Unity Serialization Support Inheritence?

I am having trouble saving custom child classes in my editor script. Data from the child classes is being lost. The question is, does Unity serialization support inheritance? Here is an example of the problem:

// Serialize
[System.Serializable]
public ParentClass()
{
  public string someString = "a string";
}
[System.Serializable]
public ChildClass() : ParentClass
{
  public int someInt;
  public ChildClass(int _someInt)
  {
    someInt = _someInt;
  }
}

List<ParentClass> list = new List<ParentClass>();
list.Add(new ChildClass(5));

// Data is saved
// Exit Unity
// Data is loaded

Debug.Log(list[0].someString);
// Output: a string; Works as intended

Debug.Log((list[0] as ChildClass).someInt));
// Null Reference Exception

Unity determine the instance type via the variable type. If you store a subclass in a base class variable it gets serialized as base class.

However there is a way to use inheritance with serialization: ScriptableObject.

Your base class has to be derived from ScriptableObject. In this case Unity will remember the true type when you store a sub / child class in a base-class variable.

ScriptableObjects have to be created with ScriptableObject.CreateInstance and destroyed with Destroy.

Unity fully supports only types derived from UnityEngine.Object. A “normal” class (derived from System.Object) is not really serialized. Unity just stores the serializeable fields it can find within the class that is actually serialized (for example a MonoBehaviour that holds the reference to an instance).

I know this might be old thread, but I’d like to share my solution in case someone in the future came across this question.

In order to overcome the limitations of Unity’s serialization system you need to write your own custom system. With the help of ISerializationCallbackReceiver and a custom serializer, I was able to do just that in VFW. There’s support for polymorphic types (interfaces and abstract system objects), generics, auto-properties, delegates, readonly fields, static fields/auto-props and much more.

I have found a great answer (not the accepted one) here by @Ruzihm : Derived Class Serialization - Unity Answers

Use the [SerializeReference] decorator on the fields you want to keep their derivate values and type.

ParentClass do not expose someInt variable, that’s the reason why you can’t access it. Unity (or Mono) is doing something strange there. If you want someInt to be serialized and displayed in the inspector, you have to replace List<ParentClass> list with List<ChildClass> list.

Though this won’t allow you to add ParentClass objects to the list, because they do not have someInt. That’s how inheritance works. With the “Parent class” as you call it, you can only access the most common denominator of all classes that are based on it.

To access the added members, you have to upcast it again

ParentClass parent = new ChildClass();
Debug.Log(parent.astring);

ChildClass child = (ChildClass)parent;
Debug.Log(child.someInt);
// or
Debug.Log( ((ChildClass)parent).someInt) );

Have you tried to keep each class in its own file? Like this:

ParentClass.cs :

using UnityEngine;
using System.Collections;

[System.Serializable]
public class ParentClass
{
  public string someString = "a string";
}

ChildClass.cs :

using UnityEngine;
using System.Collections;

[System.Serializable]
public class ChildClass : ParentClass
{
  public int someInt;
  public ChildClass(int _someInt)
  {
    someInt = _someInt;
  }
}

LoadAndWrite.cs :

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class LoadAndWrite : MonoBehaviour
{
	void Start() {

		List<ParentClass> list = new List<ParentClass>();
		list.Add(new ChildClass(5));
		
		// Data is saved
		// Exit Unity
		// Data is loaded
		Debug.Log(list[0].someString);
		
		Debug.Log((list[0] as ChildClass).someInt);
	}
}

There is no “Unity Serialization”. It is C# serialization.

Serialization is the process of saving the content of an object. Inheritance in a programming concept regarding Object-Oriented pattern.

Therefore, you need to specify explicitly which class will be serialized.


As for your issue, the correct spelling is System.Serializable and not System.Serializble. And since child class inherits only public and protected variables, only those are serialized by default (unless otherwise specified).