How to show an icon in Hierarchy view

Hi,

Like the titles says, I want to know how it’s possible to show an icon next to a gameobject in the hierarchy/scene view, considering that the gameobject has a specific monoBehaviour attached to it.

Thanks a lot

1 Like

The documentation is a bit lean on this topic, but it’s possible by adding your callback to
hierarchyWindowItemOnGUI.

There you can draw custom GUI stuff for each hierarchy element.

To mark only certain items, you can use a list in the update callback. For example, you can check your items if they do contain a certain script. I did check for lights in the example.

Here’s the code:

using UnityEditor;
using UnityEngine;
using System.Collections.Generic;

[InitializeOnLoad]
class MyHierarchyIcon
{
	static Texture2D texture;
	static List<int> markedObjects;
	
	static MyHierarchyIcon ()
	{
		// Init
		texture = AssetDatabase.LoadAssetAtPath ("Assets/Images/Testicon.png", typeof(Texture2D)) as Texture2D;
		EditorApplication.update += UpdateCB;
		EditorApplication.hierarchyWindowItemOnGUI += HierarchyItemCB;
	}
	
	static void UpdateCB ()
	{
		// Check here
		GameObject[] go = Object.FindObjectsOfType (typeof(GameObject)) as GameObject[];
		
		markedObjects = new List<int> ();
		foreach (GameObject g in go) 
		{
			// Example: mark all lights
			if (g.GetComponent<Light> () != null)
				markedObjects.Add (g.GetInstanceID ());
		}
		
	}

	static void HierarchyItemCB (int instanceID, Rect selectionRect)
	{
		// place the icoon to the right of the list:
		Rect r = new Rect (selectionRect); 
		r.x = r.width - 20;
		r.width = 18;
		
		if (markedObjects.Contains (instanceID)) 
		{
			// Draw the texture if it's a light (e.g.)
			GUI.Label (r, texture); 
		}
	}
	
}

Furthermore, you can do the same in the project window via projectWindowItemOnGUI.

Happy scripting!

If you want a fast version (0.03ms vs 6ms) try this:

using UnityEditor;
using UnityEngine;
using System.Collections.Generic;

[InitializeOnLoad]
class MyHierarchyIcons
{
	static Texture2D texturePanel;
	static List<int> markedObjects;

	static MyHierarchyIcons ()
	{
		// Init
		texturePanel = AssetDatabase.LoadAssetAtPath ("Assets/art/icons/icon ui panel.psd", typeof(Texture2D)) as Texture2D;
		EditorApplication.hierarchyWindowItemOnGUI += HierarchyItemCB;
	}

	static void HierarchyItemCB (int instanceID, Rect selectionRect)
	{
		// place the icon to the right of the list:
		Rect r = new Rect (selectionRect); 
		r.x = r.width - 20;
		r.width = 20;

		GameObject go = EditorUtility.InstanceIDToObject (instanceID) as GameObject;

		if (go.GetComponent<UIPanel>()) 
			GUI.Label (r, texturePanel);
	}
}

I recently needed this and wrote a version that will cache the game object states to save on real-time performance in the editor. It lazily updates the state of the icons and won’t be 100% up to date at all times, but on every assembly reload it will refresh the state, as well as every time you add a component, and every time you select/deselect an object, which should cover most cases in practice!

197755-hierarchy-thing.png

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;

[InitializeOnLoad]
static class HierarchyIcons {

	// add your components and the associated icons here
	static Dictionary<Type, GUIContent> typeIcons = new Dictionary<Type, GUIContent>() {
		{ typeof(CameraLocation), EditorGUIUtility.IconContent( "d_SceneViewCamera" ) },
		{ typeof(Locator), EditorGUIUtility.IconContent( "d_Transform Icon" ) },
		// ...
	};

	// cached game object information
	static Dictionary<int, GUIContent> labeledObjects = new Dictionary<int, GUIContent>();
	static HashSet<int> unlabeledObjects = new HashSet<int>();
	static GameObject[] previousSelection = null; // used to update state on deselect

	// set up all callbacks needed
	static HierarchyIcons() {
		EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyGUI;

		// callbacks for when we want to update the object GUI state:
		ObjectFactory.componentWasAdded += c => UpdateObject( c.gameObject.GetInstanceID() );
		// there's no componentWasRemoved callback, but we can use selection as a proxy:
		Selection.selectionChanged += OnSelectionChanged;
	}

	static void OnHierarchyGUI( int id, Rect rect ) {
		if( unlabeledObjects.Contains( id ) )
			return; // don't draw things with no component of interest

		if( ShouldDrawObject( id, out GUIContent icon ) ) {
			// GUI code here
			rect.xMin = rect.xMax - 20; // right-align the icon
			GUI.Label( rect, icon );
		}
	}

	static bool ShouldDrawObject( int id, out GUIContent icon ) {
		if( labeledObjects.TryGetValue( id, out icon ) )
			return true;
		// object is unsorted, add it and get icon, if applicable
		return SortObject( id, out icon );
	}

	static bool SortObject( int id, out GUIContent icon ) {
		GameObject go = EditorUtility.InstanceIDToObject( id ) as GameObject;
		if( go != null ) {
			foreach( ( Type type, GUIContent typeIcon ) in typeIcons ) {
				if( go.GetComponent( type ) ) {
					labeledObjects.Add( id, icon = typeIcon );
					return true;
				}
			}
		}

		unlabeledObjects.Add( id );
		icon = default;
		return false;
	}

	static void UpdateObject( int id ) {
		unlabeledObjects.Remove( id );
		labeledObjects.Remove( id );
		SortObject( id, out _ );
	}

	const int MAX_SELECTION_UPDATE_COUNT = 3; // how many objects we want to allow to get updated on select/deselect

	static void OnSelectionChanged() {
		TryUpdateObjects( previousSelection ); // update on deselect
		TryUpdateObjects( previousSelection = Selection.gameObjects ); // update on select
	}

	static void TryUpdateObjects( GameObject[] objects ) {
		if( objects != null && objects.Length > 0 && objects.Length <= MAX_SELECTION_UPDATE_COUNT ) { // max of three to prevent performance hitches when selecting many objects
			foreach( GameObject go in objects ) {
				UpdateObject( go.GetInstanceID() );
			}
		}
	}
}

vote for this
vote for this
http://feedback.unity3d.com/unity/all-categories/1/hot/active/add-onhierarchyviewgui-to-draw-g

https://forum.unity.com/threads/free-hierarchy-window-icons-on-objects-via-interfaces.436548/

I don’t know that there’s a way to show icons in Hierarchy or Project, but in Scene view it’s simple:

function OnDrawGizmosSelected() {
    Gizmos.DrawIcon ( transform.position, "NodeIcon.tiff" );
}

The texture has to be in the Assets/Gizmos folder.