Unity allows creating custom inspectors for your own custom types, as well as its built-in types easily. But if you’re after extending unity’s built-in inspectors you’re mostly out of luck – there’s no simple API for that (Unity’s inspectors are not publicly exposed).
This post details an example as well as the code infrastructure for extending Unity’s inspectors to provide the extra functionality when you need it. It is a bit “hacky” (it uses reflection + black magic to wrap around corners where there’s no API available).
TL;DR
Grab the code this post discusses here – DecoratorEditor
Inspector Anatomy
The inspector window, like most of Unity’s editor windows is implemented as a class deriving from EditorWindow (stay tuned for an introduction post on editor windows soon).
The window then creates and holds references to multiple Editor instances that are used for the different components that make up the object being inspected.
Extending Inspectors
The general approach for extending an inspector is to create a class that will draw the default inspector GUI and then append the functionality you want to it. For example, consider the following example for extending the default inspector for MonoBehaviour derived types:
[CustomEditor(typeof(MonoBehaviour), true)] public class MyEditor : Editor { public override void OnInspectorGUI () { // Draw default GUI for MonoBehaviours base.OnInspectorGUI (); // Add whatever functionality you like here } }
NOTE: Internally, Unity keeps a dictionary that maps a type to its corresponding editor (inspector) type. This means that an inspector marked to handle MonoBehaviour (such as the one in the example above) will not be used in case there is another inspector defined for a more specific MonoBehaviour derived type.
So far, all is well, but what if there is already a custom inspector defined for a given type, and you’d like to extend it ? Unity 5 includes 122 different inspectors (see the full list here: http://pastebin.com/Kq3T8aMw). Most (if not all) are not public, so you cannot derive from them, making it hard to extend.
Solution Outline
The solution to this problem revolves around the idea of composition, not inheritance. This means that instead of deriving from the existing inspector type (which is not possible, as it’s not public), we’ll create an instance of it and delegate all required calls to it.
This is a rough sketch of how this is achieved:
- Construct a base class that follows the Decorator pattern (it uses, or “decorates” another inspector object).
- The decorator instantiates and internally holds a reference to the original inspector object (in traditional implementations of the pattern, the decorated class is usually explicitly passed into the decorator, however in this case the decorated class is private and so we have to resort to reflection for creating the instance).
- The decorator implements all public inspector methods, delegating them to the decorated instance internally.
While the internals of the DecoratorEditor class are too long to mention here, here is an example of how to use it for creating an inspector for the Transform class:
using UnityEditor; using UnityEngine; [CustomEditor(typeof(Transform))] public class MyTransformEditor : DecoratorEditor { public MyTransformEditor() : base("TransformInspector") {} public override void OnInspectorGUI() { base.OnInspectorGUI(); GUILayout.Button("Adding this button"); } }
This example shows how to use the new base class – DecoratorEditor:
- Derive a new editor class from DecoratorEditor.
- Mark it with a CustomEditor attribute, as usual (providing the class you’d like this editor to edit).
- Pass in the built-in (existing) inspector type to the base class constructor.
Conclusion
This post showed a simple example of how you can extend Unity’s built-in inspectors (DecoratorEditor). To do what it does, it uses a bit of hackery, but this gets the job done, at least until Unity decides to expose their inspectors for extension.
Thanks to this post, I’ve successfully hacked a new tool to terrain editor: https://db.tt/aFccp22r
It’s empty right now, but the most important thing is, it WORKS.
Looks awesome. I am going to continue posting more about editor extensions soon. Had a bit of a busy time but It’ll happen soon