I’m creating a custom editor for some scripts and I want to add some common functionality across all of them. Something like:
public abstract class Animal : MonoBehaviour { }
public class Dog : Animal {}
public class Cat : Animal {}
Let’s say I want to add an inspector button for each animal. I created a custom editor for the base class, but it won’t inspect the children.
[CustomEditor(typeof(Animal))]
public class AnimalInspector : Editor {
public override void OnInspectorGUI () {
//Draw some buttons or something.
}
}
The problem is that Unity doesn’t use the custom inspector if I inspect a derived class such as Dog
, and I don’t want to create copies of the same editor script just to add the same feature to two different classes.
Any Suggestions,
Peter G
[CustomEditor(typeof(Animal), true)]
Not sure if this feature existed when you asked the question, but to include children, you use the overloaded CustomEditor(inspectedType : System.Type, editorForChildClasses : boolean).
http://docs.unity3d.com/Documentation/ScriptReference/CustomEditor.CustomEditor.html
Looking at the code, it appears that Unity indeed compares the exact type, thus not supporting Polymorphism for CustomEditors. You could file a bug on it, it’s probably a simple change, but also probably not the most demanded feature.
For now, it seems you’ll have to create a separate Editor class for each derived class - though you should not need to duplicate your scripts, why not have all the Editors derive from one base Editor class?
Here is a pattern that is suitable for many use cases, and isn’t too difficult to maintain:
Continuing with your example: When you create your base custom editor, move all of its GUI draw code to a static method. Something like:
[CustomEditor(typeof(Animal))]
public class AnimalInspector : Editor {
public override void OnInspectorGUI () {
DrawInspectorGUI((Animal)target);
}
public static bool DrawInspectorGUI (Animal targ) {
// Draw some buttons or something.
// Use the return value to indicate that the editor was updated.
}
}
When you extend the base MonoBehaviour, you can implement it’s custom editor as follows:
[CustomEditor(typeof(Dog))]
public class DogInspector : Editor {
public override void OnInspectorGUI () {
Animal.DrawInspectorGUI((Animal)target);
// Place Dog specific GUI elements here.
}
}
Another thing you could do (in addition to jonas’s answer) is to use generics and reflection to add the subclasses CustomEditor attribute. What you would need to do is redefine AnimalInspector to look like this:
public abstract class AnimalInspector<T> : Editor, where T : AnimalInspector<T>
{
//do generic Animal stuff
}
And a client class would look like this:
public class DogInspector : AnimalInspector<Dog>
{
//Do doggy stuff
}
Then, you would in a post build script reflect all classes that extend AnimalInspector, get typeof(T), then add the CustomEditor attribute there.
It is a bit roundabout, but I think it would work.
Another way you could do it is to recursively iterate over all subclasses in reflection. Then, when you found a subclass, add a CustomEditor attribute to the superclass. Again, annoying, but I think it could work.
I know it’s an old question, but the newest version (4+) of Unity offer an alternative:
[CustomEditor(typeof(MyBaseClass), true)]
The second parameter is listed as “Editor For Child Classes”.
However, it only works for direct hierarchy and interface implementation is not supported. (bleh)
Also, using typeof(UnityEngine.Object)
as base class is also not supported, assuming you would like your editor to show up on any kind of object.
I’m not sure if this was also available before, but now you can have your child class’ editor extend your base editor class:
[CustomEditor(typeof(Animal))]
public class AnimalInspector : Editor {
public override void OnInspectorGUI () {
//do your base class editor stuff here
}
}
//child class extends AnimalInspector
[CustomEditor(typeof(Dog))]
public class DogInspector : AnimalInspector {
public override void OnInspectorGUI () {
//call base editor class
base.OnInspectorGUI();
// Place Dog specific GUI elements here.
}
}