Editor Script to set Icons impossible?

Greetings,

Can I access these via an Editor Script?

1283722--58158--$icons.png

I have read up on Gizmos, Handle.Label and such, but none of them are suitable. I have found no information
on this.
It would be fantastic to simply access and set icons and icon colors to which ever object(s) we wish via an editor window in bulk!

I decided to come here before going to the suggestions page since I feel perhaps I am over looking something I am not able to find via a simple google search.

Thank you for any info in advance!

Bump Surely someone must know at least if it is possible or not? :face_with_spiral_eyes:

I’d love to know this too.

There’s Gizmos.DrawIcon(…) but it’d be super handy if I could just use one of these.

+1

Yes this I am aware of, and I found that if you set [CustomEditor (typeof(GameObject))] you can access the texture inspector for the Icon, so it’s as if they are just using DrawIcon, this might be the solution.

I will test it first, but it might just be Gizmos.DrawIcon and accessing the icons within the Unity files (if they are accessible)!

edit:

I have found that it ā€œworksā€ but the names of the objects don’t come up. Feels like jumping through hoops when one could just set ā€œgizmos.Iconā€ for example. Will add this to the suggestions page since I presume it is NOT possible to get icons with the names set via script.

The best solution for this so far has been to assign empty scipts with Icons to the game objects. This will take the gameobject name and the script color.

However this is messy and shouldn’t be necessary at all. Hopefully Unity guys will sort this out I see no reason why:
a) we cannot set icons to multiple objects and selections
b) why we can’t access the icon option from Gizmo

Quite old thread, but…

I have investigated this today, as I saw a question related to object icons at Unity Answers. It is possible to assign an icon, but you have to use reflection. Example:

using UnityEngine;
using UnityEditor;
using System.Reflection;

public class CreateObject : Editor
{
    [MenuItem("Tools/Create object with icon")]
    static void CreateSphereWithIcon()
    {
        Texture2D icon = (Texture2D)Resources.Load("CustomIcon");
        var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);

        var editorGUIUtilityType = typeof(EditorGUIUtility);
        var bindingFlags = BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic;
        var args = new object[] { go, icon };
        editorGUIUtilityType.InvokeMember("SetIconForObject", bindingFlags, null, null, args);
        //var editorUtilityType = typeof(EditorUtility);
        //editorUtilityType.InvokeMember("ForceReloadInspectors", bindingFlags, null, null, null);
    }
}

ForceReloadInspector method is called in original source (inside UnityEditor.IconSelector.DoButton method), but when I tested above solution, the call was not required. I left these lines here ā€˜just in case’, so if there are any problems, maybe uncommenting them will help.

1 Like

This does not work anymore as SetIconForObject has been removed from EditorGUIUtility

For anyone who is still wondering how to do this, I made a script that does this.

using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;

public class IconManager {

    public enum LabelIcon {
        Gray = 0,
        Blue,
        Teal,
        Green,
        Yellow,
        Orange,
        Red,
        Purple
    }

    public enum Icon {
        CircleGray = 0,
        CircleBlue,
        CircleTeal,
        CircleGreen,
        CircleYellow,
        CircleOrange,
        CircleRed,
        CirclePurple,
        DiamondGray,
        DiamondBlue,
        DiamondTeal,
        DiamondGreen,
        DiamondYellow,
        DiamondOrange,
        DiamondRed,
        DiamondPurple
    }

    private static GUIContent[] labelIcons;
    private static GUIContent[] largeIcons;

    public static void SetIcon( GameObject gObj, LabelIcon icon ) {
        if ( labelIcons == null ) {
            labelIcons = GetTextures( "sv_label_", string.Empty, 0, 8 );
        }

        SetIcon( gObj, labelIcons[(int)icon].image as Texture2D );
    }

    public static void SetIcon( GameObject gObj, Icon icon ) {
        if ( largeIcons == null ) {
            largeIcons = GetTextures( "sv_icon_dot", "_pix16_gizmo", 0, 16 );
        }

        SetIcon( gObj, largeIcons[(int)icon].image as Texture2D );
    }

    private static void SetIcon( GameObject gObj, Texture2D texture ) {
        var ty = typeof( EditorGUIUtility );
        var mi = ty.GetMethod( "SetIconForObject", BindingFlags.NonPublic | BindingFlags.Static );
        mi.Invoke( null, new object[] { gObj, texture } );
    }

    private static GUIContent[] GetTextures( string baseName, string postFix, int startIndex, int count ) {
        GUIContent[] guiContentArray = new GUIContent[count];

        var t = typeof( EditorGUIUtility );
        var mi = t.GetMethod( "IconContent", BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof( string ) }, null );

        for ( int index = 0; index < count; ++index ) {
            guiContentArray[index] = mi.Invoke( null, new object[] { baseName + (object)(startIndex + index) + postFix } ) as GUIContent;
        }

        return guiContentArray;
    }
}
5 Likes

Thanks. I used this script and it worked. However, it seems like the IconContent has been changed to a ā€œpublic staticā€ method, so the binding flag on line 67 has to be changed to BindingFlags.Public | BindingFlags.Static for it to work. :slight_smile:

2 Likes

Here’s a version that’s less flexible, but more concise and maybe a little easier to follow:

  public static void AssignLabel(GameObject g)
  {
    Texture2D tex = EditorGUIUtility.IconContent("sv_label_0").image as Texture2D;
    Type editorGUIUtilityType  = typeof(EditorGUIUtility);
    BindingFlags bindingFlags = BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic;
    object[] args = new object[] {g, tex};
    editorGUIUtilityType.InvokeMember("SetIconForObject", bindingFlags, null, null, args);
  }
6 Likes

That works so well. Thank you.

Hi, I tried to use thudernerd’s script but icons are not changing, clearly I’m doing something wrong. How is this script suposed to be used?
Thank You.

update:
Im getting this error using the script:

NullReferenceException: Object reference not set to an instance of an object
IconManager.GetTextures (System.String baseName, System.String postFix, Int32 startIndex, Int32 count) (at Assets/Scripts/IconManager.cs:70)

This is the Line with the error:

guiContentArray[index] = mi.Invoke( null, new object[] { baseName + (object)(startIndex + index) + postFix } ) as GUIContent;

I’ve put the source on my github with an updated version for 5.3 and higher.
I’ve also added extension methods for GameObjects to eliminate the call to IconManager (you’re still free to do so though)

It’s available here: https://github.com/Thundernerd/Unity3D-IconManager

2 Likes

Thx!
do I need the ProjectSettings folder in my project too?

Nah you just need the IconManager code file tbh

Super handy script! Thx…

Thank you so much from 2018 :slight_smile:

Is this possible to permanently change a monobehaviour’s icon like this ?

I used @delzhand 's snippet to build my own editor window. While it works fine with scene objects and prefab assets, the changes on scripts won’t persist after I restart Unity.

It sounds like the objects aren’t marked as dirty, and maybe the scene isn’t either. Are you sure that’s happening?