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