Serialized and derived classes

I have some objects I’d like to initialize at editor time because they involve long calculations that takes too long at runtime.

One of these object have a variable of a base class type, which is initialized with an object of a derived type. Both base class and derived class are serializable. Normally, when I do the initialization at runtime things work perfectly, but when I try to initialize at editor time instead, things go wrong:

Apparently Unity doesn’t remember that the object is of a derived type and thinks it is of the base type instead…

Try for yourself:

  • Drag the first script onto an empty game object.
  • Put the second script in an asset folder named “Editor”.
  • Select from the menu bar: Custom > Initialize Derived Object
  • Press the Play button.

What I see here is that upon initialization (at editor time) the type is reported as “TestDerived” while at runtime the type is now reported as “TestBase”. Thus the method calls go to the base class and not the derived class.

Is this a bug in Unity or have I misunderstood something?

TestDerivedCaller.cs

using UnityEngine;
using System.Collections;

[System.Serializable]
public class TestBase {
	public float[] values;
	public virtual void SetValues(float[] val) { throw new System.NotImplementedException(); }
	public virtual float[] GetValues() { throw new System.NotImplementedException(); }
}

[System.Serializable]
public class TestDerived : TestBase {
	public override void SetValues(float[] val) { values = val; }
	public override float[] GetValues() { return values; }
}

public class TestDerivedCaller : MonoBehaviour {
	
	public TestBase myBase;
	public bool initializeObjectAtRuntime = false;
	public bool queryObject = true;
	
	// Use this for initialization
	void Start () {
		if (initializeObjectAtRuntime) Init();
	}
	
	public void Init() {
		float[] myFloats = new float[] {2,3,4};
		myBase = new TestDerived();
		myBase.SetValues(myFloats);
		Debug.Log("Init(): myBase is of type "+myBase.GetType());
	}
	
	// Update is called once per frame
	void Update () {
		Debug.Log("Update (): myBase is of type "+myBase.GetType());
		if (queryObject) myBase.GetValues();
	}
}

TestEditorClass.cs

using UnityEditor;
using UnityEngine;

class TestEditorClass {
	[MenuItem ("Custom/Initialize Derived Object")]
    static void Call() {
        GameObject activeGO = Selection.activeGameObject;

        TestDerivedCaller caller =
        	activeGO.GetComponent(typeof(TestDerivedCaller)) as TestDerivedCaller;
        caller.Init();
    }
}

Thanks,
Rune

Did you find a solution to this? I’m banging my head against it as well. No matter what I do, Unity serializes the derived class as the base class.

Are you absolutely certain that the problem is what you’re saying it is? I have no trouble having one serializable class inherit from another serializable class.

Pretty sure. The problem isn’t serializing derived classes in general, it’s serializing derived classes when they’re typed as their base classes. For example, when you have an array typed as BaseClass[ ] and fill it with instances of DerivedClassA and DerivedClassB. When you re-open the scene, those instances will have become instances of BaseClass.

I made a project that reproduces the issue and submitted a bug report. Though I’m still hoping I’ve just made a stupid error somewhere. It would make my life a lot easier if I could get this to work. :slight_smile:

121908–4587–$bug_with_serialization_885.zip (490 KB)

I think you might be on the wrong track for the source of the issue there.

From what I remember, the problem is not the BaseClass nor the serialize.
The problem is doing it through a collection, which will effectively only hold baseclasses.

there are a few topics on this (array + serialize especially)

Thanks! That made me find this thread where Joe says that this is simply how Unity serializes arrays, unless (!) you inherit from ScriptableObject. So I tried that, and now the derived classes get serialized properly. Hooray!