SerializedProperty and abstract custom classes

I can’t seem to get a serialized property to a reference of an abstract custom class in a MonoBehaviour:

using UnityEngine;
using System;

public class AbstractFieldsTest : MonoBehaviour
{
	public NestedAbstract nested;
	public OuterAbstract outer;

	[Serializable]
	public abstract class NestedAbstract { }
}

[Serializable]
public abstract class OuterAbstract { }

(I have both a nested and an outer class just to demonstrate that it doesn’t matter - cause in my use-case the class was nested)

using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(AbstractFieldsTest))]
public class AbstractTestEditor : Editor
{
	public override void OnInspectorGUI()
	{
		var spOuter = serializedObject.FindProperty("outer");
		var spNested = serializedObject.FindProperty("nested");
		Debug.Log(spOuter);
		Debug.Log(spNested);
	}
}

Both the logs print out “Null” - If I make the classes non-abstract, the serialized properties get assigned properly.

Is there a way around this? or is this just how it works?

You might ask about my use case: I have an abstract reference marked up with a custom attribute that allows me to assign it an instance from the inspector from a popup menu displaying all it’s children types (I use Activator.GetInstance to create an actual object)

Thanks for any help.

EDIT:
Making the classes ScriptableObjects didn’t help either for some reason.

using UnityEngine;
using System;
using ShowEmAll;

public class AbstractFieldsTest : BetterBehaviour
{
	[HideInInspector, SerializeField] public NestedAbstract nested;
	[HideInInspector, SerializeField] public OuterAbstract outer;

	[Serializable]
	public abstract class NestedAbstract : ScriptableObject { }

	[Serializable]
	public class NestedChild : NestedAbstract { }

	[ShowMethod]
	public void Assign()
	{
		//outer = new OuterChild();
		//nested = new NestedChild();
		outer = ScriptableObject.CreateInstance<OuterChild>();
		nested = ScriptableObject.CreateInstance<NestedChild>();
	}

	[ShowMethod]
	public void Print()
	{
		Debug.Log(outer);
		Debug.Log(nested);
	}
}

[Serializable]
public abstract class OuterAbstract : ScriptableObject { }

[Serializable]
public class OuterChild : OuterAbstract { }

(ShowMethod is just an attribute I use to make the method visible and invokable from the editor for quick testing)

Well, first from the editor I invoke “Assign” - But if I print out the results, the “nested” reference is null - Kind of off-topic here but it seems that SOs don’t play well with nested classes?

The “outer” reference is assigned OK. And it’s also picked up from the SerializedProperty in the test editor. Now when I enter playmode, and invoke “Print” to see if the “outer” reference is still intact, I see that it’s now null as well! Am I missing something here?

Well since you’re already a long-time-Unity-user i thought you already know how the serialization system works :wink: I recommend to read this great blog post by Lucas Meijer

Custom classes aren’t serialized as “reference”. The content of the class is serialized “in-place”. The serialization system also does not support inheritance / polymorphism. When such a class is deserialized, Unity creates an instance of the variable type. It doesn’t know what type of class was referenced when it get serialized.

You should set the serializarion mode in the editor settings to “force text”. Just open an asset, for example your scene file, and see how the data got serialized and what information about the class is actually there.

Inheritance / polymorphism is only supported when using MonoBehaviour or ScriptableObject classes as they are serialized on their own. Unity can only serialize references to UnityEngine.Object classes.

ps: you should especially read the section “No support for polymorphism” in the blog post.