Overview
Click To Download Full Source Code
This post shows how to add GUI elements to the game objects in the Hierarchy Window in Unity. You can add elements like toggles, buttons, and icons/images to the game objects in the hierarchy.
Example:
Now, I’m not a fan of the whole ‘process’ where I have to select a gameobject, move my mouse pointer all the way to the inspector and click on the check box at the top to deactivate it. So, let’s create a toggle in the hierarchy itself that’ll help us quickly activate and deactivate a game object.
Create a new script and name it HierarchyGUI.cs. This script won’t be attached to any of the game objects in our scene, so it doesn’t need to inherit from MonoBehaviour. Also, get rid of the Start() and Update() methods and add the UnityEditor namespace.
We want the script to ‘launch’ as soon as Unity starts without requiring any action from the user. To achieve that, we use the InitializeOnLoad attribute just above the class declaration and by creating a static constructor of the class like so:
using UnityEngine; using System.Collections; using UnityEditor; [InitializeOnLoad] public class HierarchyGUI : MonoBehaviour { //constructor static HierarchyGUI () { } }
Inside the constructor, subscribe to EditorApplication.hierarchyWindowItemOnGUI. It’s a Delegate to be called for every visible list item in the Hierarchy Window on every OnGUI event.
Next, create the method that is subscribed to the Delegate. Two parameters come with the Delegate: the instance ID of the object and its rect.
Your script should now look something like this:
using UnityEngine; using System.Collections; using UnityEditor; [InitializeOnLoad] public class HierarchyGUI : MonoBehaviour { //constructor static HierarchyGUI () { EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyGUI; } static void OnHierarchyGUI(int instanceID, Rect selectionRect) { } }
Inside the OnHierarchyGUI() method, we use the instance IDs to get the game object references.
//get the gameObject reference using its instance ID GameObject go = (GameObject)EditorUtility.InstanceIDToObject(instanceID);
Get the rect of the selection and set its x position equal to the width. This will place the toggle on the right of the selection and prevent it from overlapping with the name of the game object.
//get rect m8 Rect rect = new Rect (selectionRect); rect.x = rect.width;
Finally, create the toggle using GUI.Toggle and position it using the rect.
//toggle bool toggleStatus = GUI.Toggle(rect, go.activeInHierarchy, ""); go.SetActive(toggleStatus);
Save and go check your Hierarchy Window. There should be a toggle next to every game object in your Hierarchy Window which will activate/deactivate the game object.
You can also add text labels just to highlight specific game objects. But, instead of adding one to every game object in the scene, let’s create a game object called Game Manager and add the label only to it.
The code will sift through all the objects in the Hierarchy Window, identify the Game Manager and add the label only to it. We’ll use the MenuItem attribute to call a method from the hierarchy context menu.
The MenuItem attribute is used to add a context menu. We add it to the GameObject menu inside the Marker submenu and call it GameManager. It shows up when you right click on a game object in the Hierarchy Window. Go to Marker>GameManager to ‘mark’ the game object. We use the instance ID of the game object to ‘remember’ its ID and use EditorPrefs to save the string. EditorPrefs are like PlayerPrefs but for the Editor. We also put in an else in case you want to remove the game object as the Game Manager.
Since we’ll be using the Instance ID for more than 1 marker, we add a suffix to it for each one of our markers. I used ‘G’ for Game Manager, ‘UI’ for UI, and ‘toggle’ for the Toggles.
[MenuItem("GameObject/Marker/GameManager", false, 1)] static void AddGameManagerMarker() { foreach(Object o in Selection.gameObjects) { if(EditorPrefs.GetInt(o.GetInstanceID()+"G")==0) { EditorPrefs.SetInt(o.GetInstanceID()+"G", 1); } else { EditorPrefs.SetInt(o.GetInstanceID()+"G", 0); } } }
The code only sets the EditorPrefs for the selected game object. It doesn’t add the text label yet. To add one, we need to go back to the OnHierarchyGUI() method.
We check if a game object is ‘marked’ as the Game Manager. If it is, we add a text ‘G’ to it using GUI.Label. We also move the rect a bit to the left so it doesn’t overlap with the Toggle we added earlier.
//GM marker if(EditorPrefs.GetInt(go.GetInstanceID()+"G")==1) { rect.x = rect.width-15; GUI.Label(rect, "G"); }
Note that calling the method again removes the marker.
Instead of adding toggles to every game object, we can use the same logic to add the toggle to specific game objects.
We can also add tiny images as icons instead of just plain, boring text labels. First, we declare a Texture2D and a GUIStyle.
static Texture2D UITexture; static GUIStyle style;
Create a ‘Resources’ folder in the Assets folder and put an image inside it.
Load it using Resources.Load(name_of_the_image) inside the constructor like so:
UITexture = (Texture2D)Resources.Load("UI Texture"); //new guistyle for the markers style = new GUIStyle();
I used the image to mark UI game objects in the scene. You’ll need to set the height and width of the rect so the icon appears in the correct position.
//UI marker if(EditorPrefs.GetInt(go.GetInstanceID()+"UI")==1) { rect.x = rect.width-15; rect.width=15; rect.height=rect.height-2; //use the texture as the background for the style style.normal.background = UITexture; //use the style in the GUI label. GUI.Label(rect,"", style); }
That’s all. You can also create a method to remove all the markers so you don’t need to select each one of them individually.
//Remove all markers [MenuItem("GameObject/Marker/Remove", false,13)] static void RemoveMarkers() { foreach(Object o in Selection.gameObjects) { EditorPrefs.SetInt(o.GetInstanceID()+"toggle", 0); EditorPrefs.SetInt(o.GetInstanceID()+"G", 0); EditorPrefs.SetInt(o.GetInstanceID()+"UI", 0); } }