Search Unity

Custom Asset Icons?

Discussion in 'Editor & General Support' started by Nemox, Jan 9, 2012.

  1. Nemox

    Nemox

    Joined:
    Feb 16, 2010
    Posts:
    396
    So I'm starting to make some custom assets, and I wonder if there's any way I can give them custom icons to distinguish them, instead of that silly paper-with-bent-corner indicating it's based on a script. Quite like that little island-with-palm-tree icon that Terrains have.

    Anyone know how this might work?
     
    MilenaRocha likes this.
  2. andsee

    andsee

    Joined:
    Mar 20, 2012
    Posts:
    88
    I've been searching to do the same thing but no luck so far. If I do find out definitavly one way or the other I'll post here.
     
  3. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Yes, this would be useful. There seems to be two places where custom icons would be useful (both as with the terrain asset)

    - MonoBehaviour scripts when added as components to an object. A different variation of the terrain icon is used. This is nice because it helps emphasize that it is the important component.

    EDIT: This can be achieved: http://answers.unity3d.com/questions/7983/changing-the-inspector-titlebar-icon-and-text.html

    - Asset File - as mentioned.
     
    Last edited: Jun 8, 2012
  4. shkar-noori

    shkar-noori

    Joined:
    Jun 10, 2013
    Posts:
    833
    how can i set the inspector icon for a MonoBehaviour in a compiled C# plugin?
     
  5. nbg_yalta

    nbg_yalta

    Joined:
    Oct 3, 2012
    Posts:
    378
    Same question, did you find any solution?
     
  6. shkar-noori

    shkar-noori

    Joined:
    Jun 10, 2013
    Posts:
    833
    nope.
     
  7. IzzySoft

    IzzySoft

    Joined:
    Feb 11, 2013
    Posts:
    376
    It be cool if there was a MonoBehaviour class attribute for compiled .net DLL's
    ex:
    Code (csharp):
    1.  
    2. [IconTexture( "Assets/MyPlugin/Editor/Resources/kissCamera.png" )]
    3. public class kissCamera : MonoBehaviour
    4. {
    5. //...
    6. }
    7.  
    but this should work too for a compiled dll MonoBehaviour:
     
    Last edited: May 2, 2015
    AlanMattano and samana1407 like this.
  8. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,090
    I just figured out how to do this. Follow these steps:
    1. Turn on Visible Meta Files in both your source code project and your DLL/Assembly project.
    2. For a custom MonoBehaviour that you want an icon for, locate the script file in your project and set the icon to a custom icon. E.g. CustomBehaviour.cs.
    3. Open your source code project in Explorer (Win) or Finder (Mac) and locate your CustomBehaviour.cs file. Next to it will be a CustomBehaviour.cs.meta file. This is a text file.
    4. Open the meta file in your favorite text editor. Make note of the line that reads "icon: {...}".
      {fileID: 2800000, guid: 6416ff...4830a, type: 3}
    5. Open the project with your DLL/Assembly compiled plugin.
    6. Locate the meta file associated with the DLL/Assembly that contains your CustomBehaviour class.
    7. Find the line that reads "iconMap: {}".
    8. Delete the curly braces next to "iconMap" and add a new line.
    9. Enter four spaces to indent below the "iconMap:" line, write the name of your class followed by a colon (":"), and then copy everything in the curly braces (including the braces) from step 4 above and paste it to the end. It should look like this:
      Code (YAML):
      1. ...
      2.   iconMap:
      3.     CustomBehaviour:  {...}
    10. If your class is in a namespace, it would look like the following:
      Code (YAML):
      1. ...
      2.   iconMap:
      3.     Name.Space.CustomBehaviour:  {...}
    If you create a package to export in a project with these modified meta files, those settings will be stored in the exported unitypackage file. This means that they will transfer when imported to a different project, even if that project doesn't have visible meta files turned on!

    I have only tested as early as Unity 4.5.5 and it works partially there (icon appears everywhere but in the "Add Component" menu). This works completely for Unity 4.6+, however.
     
  9. IzzySoft

    IzzySoft

    Joined:
    Feb 11, 2013
    Posts:
    376
    Sweet.

    It be cool if (on Unity 5.0.2) Project View would also read the iconMap... because its not showing the icon there. But the Inspector is reading the iconMap.

    ex:
    Code (CSharp):
    1. PluginImporter:
    2.   iconMap:
    3.     kissUI.kissLayoutAsset: {fileID: 2800000, guid: 9a76736e44bebbe44b7b32b187275b58, type: 3}


    Only way to get this to show the icon in the Project View, is to place it in the Assets/Gizmos folder. :/
    I was hoping for a way to Avoid having to have a Assets/Gizmos folder with the icons. :/
    Ohh well. :/
     
    Last edited: Dec 30, 2015
  10. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,090
    Right. The Project folder view does its own thing. My guess is that they use different icons because the size of the icons in the Project View can be much larger when "zoomed in". It would be really nice to have better, more universal support for icons. As for Custom Assets (ScriptableObject based assets), adding the iconMap setting and having the icon set in Assets/Gizmos seems to work the best. I've encountered a situation where the Inspector doesn't read the icon from Assets/Gizmos (in my case it was drawn with EditorGUILayout.PropertyField). Adding the iconMap setting for the asset type solved that issue.
     
  11. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    You can have custom previews in the project window for custom ScriptableObject's.
    1. Create a custom ScriptableObject class.
    2. Create a custom Editor for the custom ScriptableObject class.
    3. Override and implement your custom preview in YourCustomEditor.RenderStaticPreview.
     
    Khartraxx, Wisteso and samana1407 like this.
  12. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,090
    Awesome! Thanks for the heads up on that! It's good to know that RenderStaticPreview will fall back on the default icon:
    Presumably you could add support for your own icon this way and simply always return the icon itself as the Texture2D. That way you might be able to sidestep the Assets/Gizmos trick for the Project view(?). However, you would still need the iconMap trick (or equivalent with raw source files) to get the icon (not custom preview) to show up in the Inspector when used as a property.
     
  13. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
    Maybe i'm missing something, but you can do this:

    (if you chose 'other' you can select your own texture),
    and it looks like this (if it's a scriptableObject, assets will have the icon too):
     
    rakkarage likes this.
  14. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,090
    The thing you are missing is that you can't set that icon as you've shown there when the script is compiled into an assembly (a DLL). For that you need the steps listed above.

    Yes, but that does not work for the Project view. Simply setting that icon will work for Inspector properties but the asset will still show a "default asset icon" in the Project view.
     
  15. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
    For the first part, yes. But as for the Project view, it works for me:
     
  16. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,090
    That is the Script Asset for the ScriptableObject class, not a custom asset file (a serialized instance of your "WorldGrid" class). Serialized instances that you can see in the Project view are what I'm referring to. Like this:
    20140724014803.jpg
     
  17. IzzySoft

    IzzySoft

    Joined:
    Feb 11, 2013
    Posts:
    376
    The Inspector doesnt give the "Select Icon: Other" Option when you click on the Class that's part of an Assembly.
    ex:
     
    SonicBloomEric likes this.
  18. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
    @SonicBloomEric, i'm sure that was the behaviour, instance-assets got the icon too (i worked with that on a project, that's why i wrote that). But i just tested it, and it seems this behaviour was changed in a recent unity version and now it doesn't display the icon anymore.
     
  19. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,090
    If you say so, @ValooFX! :) I've tested on Unity 4.5.5, 4.6.9, 5.0.4, 5.1.4, 5.2.4, and 5.3.1 and they have all acted the same way*... :/

    *Well, Except Unity 4.5! The "iconMap" implementation appears to be disregarded in the "Add Component" menu. This works in Unity 4.6+ (which makes sense because that's when they started shipping UnityEngine.UI and needed the feature internally, too).
     
  20. Flavelius

    Flavelius

    Joined:
    Jul 8, 2012
    Posts:
    945
  21. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,090
    Interesting. That seems to work as you described (in at least Unity 5.1 and 5.3... couldn't test earlier because of your use of [CreateAssetMenu]). I was working from a base of Unity 4.5 and IIRC, that simply didn't work... Maybe something was fixed? Or I missed something?

    This only worked partially for me. For the asset that you had packed in the unitypackage, the icon didn't appear to work. However, it did work when I made a new one. See:
    Screen Shot 2016-01-03 at 9.54.51 PM.png
    :-/

    Also, props for the interesting method! Seems pretty neat! I like how you don't even need the texture asset anymore ;) [Though the size of the Editor class rises commensurately...]
     
  22. GearKlik

    GearKlik

    Joined:
    Sep 21, 2015
    Posts:
    58
    Slight necroing, any way to set icons for text assets with a specific file extension?
     
  23. SonicBloomEric

    SonicBloomEric

    Joined:
    Sep 11, 2014
    Posts:
    1,090
    There is no official way to accomplish this with legacy Unity. Unity 2017.1, however, included a new set of experimental APIs called Asset Importers. From the ScriptedImporter documentation (emphasis mine):

    It seems that the ScriptedImporterEditor class' RenderStaticPreview function may provide you with the hooks you need, but it does require quite a bit of setup.

    That said, it sounds like this entire system is something you'd benefit from, given that you have "text assets with a specific file extension". This system would allow you to turn those simple text assets into full-featured Unity assets.
     
    grobonom and Flavelius like this.
  24. Fydar

    Fydar

    Joined:
    Feb 23, 2014
    Posts:
    69
    I have produced an asset that does exactly this! The original question asks for the ability to distinguish the Assets from eachother, so I hope this is exactly what you guys are looking for.I always wanted to do it in my projects so I set aside some time and finally produced the asset :)

    It allows for Dynamic ScriptableObject icons with a single attribute! If you love ScriptableObjects, then you will love this asset :)

    https://www.assetstore.unity3d.com/en/#!/content/100547

    All of the above solutions, per script icons and using Gizmos only allows for one icon for every ScriptableObject, but my asset sources the icon from the ScriptableObject's data.
     

    Attached Files:

  25. Fydar

    Fydar

    Joined:
    Feb 23, 2014
    Posts:
    69
    @GearKlik If your interested, I could update my asset to include custom icons on any asset depending on the file extension?

    You know what, why not - next update inbound ;)
     
  26. BelkaDevHH

    BelkaDevHH

    Joined:
    Jun 12, 2018
    Posts:
    1
    Weird thing, when I override RenderStaticPreview() method, I see actual sprite only when Project View icon scale slider is not in it very left position. If I move this slider to display smallest icons possible - it renders default scriptable object icon. How to solve that?
    unity_custom_icons.png
     
    Last edited: Jun 12, 2018
    antoined73 and lmgginspace like this.
  27. lmgginspace

    lmgginspace

    Joined:
    Nov 22, 2012
    Posts:
    34
    I'd like a lot to know how to solve that too
     
  28. antoined73

    antoined73

    Joined:
    Feb 23, 2014
    Posts:
    24
    Still no clue how to solve that ?
    Also, the icon is not rendered as a proper png even if the source Texture2D is
     
  29. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    374
    I used ScriptedImporters a little while ago -- this probably doesn't help with built-in types or your C# scripts/ScriptableObjects, but works for importing custom file extensions as assets.

    For a particular file extension, you can write a ScriptedImporter that uses the AssetImportContext class' AddObjectToAsset(string, Object, Texture2D) method. The Texture2D argument is your custom icon.

    For a nice example, I made a ScriptedImporter that works on ".lua" files so I could make better support for Lua scripting in Unity for my game. This is the editor code I used in Unity 2020.2.0a12 (though it's worked for a while before 2020.2 Alpha):

    Code (CSharp):
    1. using System.IO;
    2. using UnityEngine;
    3. using UnityEditor;
    4. using UnityEditor.Experimental.AssetImporters;
    5.  
    6.  
    7. /// <summary>
    8. /// A custom scripted importer that handles importing ".lua" files as text assets.
    9. /// </summary>
    10. [ScriptedImporter(1, "lua")]
    11. public class LuaScriptImporter : ScriptedImporter {
    12.     [SerializeField] private TextAsset luaScript;
    13.  
    14.     public override void OnImportAsset(AssetImportContext ctx) {
    15.         string fileText = File.ReadAllText(ctx.assetPath);
    16.         luaScript = new TextAsset(fileText);
    17.  
    18.         Texture2D icon = Resources.Load<Texture2D>("Editor/Icons/LuaScript Icon");
    19.         ctx.AddObjectToAsset("Lua Script", luaScript, icon);
    20.         ctx.SetMainObject(luaScript);
    21.     }
    22. }
    23.  
    This importer can remember serialized data for your custom asset, so my `luaScript` instance field is remembering the TextAsset I made when I imported the ".lua" file.

    Note Lines 18-19, where I load the icon and set it with the asset.
    I just load my Texture2D (icon) using Resources, and add the TextAsset with that icon to the "asset import context" -- and that icon becomes what is used for that asset, since the TextAsset there is set to be the main object.

    In my example, I have a Resources/Editor/Icons/ folder containing "LuaScript Icon.png".