Let’s draw on Unity’s Hierarchy Window


What I like about the Unity engine is that it can be easily customized to your own needs. Existing windows like hierarchy, inspector etc. are extensible and you can also create your own windows.

Custom windows in Unity can greatly improve your workflow by giving you the additional information you need. It can also make the editor more fun to use by customizing the look of the editor to your aesthetic preferences.

I’d like to show a starting point for customizing the hierarchy window. As an example, we will add some gradients to it:

If you just want to skim through the project, you can find it in GitHub.

1. Setting up

Either create a new project or open an existing one in Unity3D. This tutorial is written with Unity 2021.2, but it should work with older versions as well.

Make an Editor folder and create a new script under it. Editor folder is necessary for excluding the scripts from the final build of the game.

Add Editor folder and place a new script under it

2. Preparing the script

We do not need to extend on MonoBehaviour so erase that part from your class description. So far our script looks like this:

namespace GradientHierarchy.Editor
{
  public class GradientHierarchyDrawer 
  {
        
  }
}

We want our class to be loaded whenever Unity starts or our code recompile. [InitializeOnLoad] attribute tells Unity to call the static constructor of this class whenever it gets loaded. You can add a Debug.Log to see yourself when the Constructor is called.

using UnityEditor;
using UnityEngine;

namespace GradientHierarchy.Editor
{
  [InitializeOnLoad]
  public class GradientHierarchyDrawer
  {
    static GradientHierarchyDrawer()
    {
      Debug.Log("Unity is loaded");
    }
  }
}

If we want to draw on the hierarchy window, we need to somehow get notified when an item is drawn on it. Unity has an delegate function we can register to: EditorApplication.hierarchyWindowItemOnGUI . This function gets called for all the visible items in Hierarchy window. It includes Scene and GameObject items. Let’s register to this function and paint all the items to see what we get.

using UnityEditor;
using UnityEngine;

namespace GradientHierarchy.Editor
{
  [InitializeOnLoad]
  public class GradientHierarchyDrawer
  {
    static GradientHierarchyDrawer()
    {
      EditorApplication.hierarchyWindowItemOnGUI += 
        HierarchyWindowItemOnGUIHandler;
    }

    private static void HierarchyWindowItemOnGUIHandler(int instanceId, Rect selectionRect)
    {
      var backgroundColor = new Color(0.75f, 0.57f, 0.99f);
      EditorGUI.DrawRect(selectionRect, backgroundColor);
    }
  }
}

3. Understanding the inputs we get

Let’s look at the arguments we get: (int instanceId, Rect selectionRect)

instanceId

it is a unique identifier for unity objects. It can be used to get a reference to the actual GameObject. Use the following code for getting it:

var currentObject = EditorUtility.InstanceIDToObject(instanceId) as GameObject;

this function will return null for the scene headers. For the sample scene with the following Hierarchy, following instances are returned:

SampleScene         --> null
  Main Camera       --> Main Camera
  Directional Light --> Directional Light

selectionRect

It describes the rectangle in which the element is rendered. Rectangle has a position and a size. Let’s take these values for the Directional Light:

position: (60, 32)
size: (211, 16)

4. Making the gradient

We now have all the ingredients for making the gradient! Let’s put everything together:

    private static void HierarchyWindowItemOnGUIHandler(int instanceId, Rect selectionRect)
    {
      var currentObject = EditorUtility.InstanceIDToObject(instanceId) as GameObject;
      if (!currentObject)
        return;
      
      var parentComponents = currentObject.transform.GetComponentsInParent<Transform>();
      var parentCount = parentComponents.Length - 1;
      var alpha = Mathf.Clamp01(0.2f - parentCount * 0.04f);

      var backgroundColor = new Color(0.75f, 0.57f, 0.99f, alpha);
      EditorGUI.DrawRect(selectionRect, backgroundColor);
    }

Above code will render the hierarchy as following:

let’s go over the code line by line:

      var currentObject = EditorUtility.InstanceIDToObject(instanceId) as GameObject;
      if (!currentObject)
        return;

Above code we get the current game object. We do nothing if the current object is null. I did not compare the current object to null — if(currentObject==null), because of its performance impact. You can read more about this special case in Unity’s blog post.

   var parentComponents = currentObject.transform.GetComponentsInParent<Transform>();
      var parentCount = parentComponents.Length - 1;
 var alpha = Mathf.Clamp01(0.2f - parentCount * 0.04f);

Here we count how many parents does the current object have. Parent count then determines the alpha value for the background color.

      var backgroundColor = new Color(0.75f, 0.57f, 0.99f, alpha);
      EditorGUI.DrawRect(selectionRect, backgroundColor);

Then we use the alpha value to determine our background color. Finally we can draw our rectangle with the help of EditorGUI!

5. Additional references

This tutorial gives a baseline for customizing hierarchy windows. You can now add special icons for tagged game objects, or underline objects that have colliders. Possibilities are endless 😉

Some docs that you can read:

There’s also a new UI system in unity called UI Toolkit. As far as I know it can be used to customize the Editor as well, but I haven’t checked it out yet.

That’s about it. Happy customizing!