How to create custom asset icons for ScriptableObject instances

I have an item database consisting of several ScriptableObjects of type Item. These items have a public Sprite icon; field, and the behavior I want is for the icon for each asset to reflect the contents of the icon Sprite.


Currently, I am using EditorGUIUtility.SetIconForObject(asset, icon.texture); to accomplish this, but I am running into some strange issues with this that I can’t pinpoint the cause of.


Here is my current script:

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

namespace InventorySystem
{
    [InitializeOnLoad]
    public class InventorySystemEditorUtils
    {
        static InventorySystemEditorUtils()
        {
            List<Item> items = FindAssetsByType<Item>();
            items.ForEach(item =>
            {
                Item obj = AssetDatabase.LoadAssetAtPath<Item>(AssetDatabase.GetAssetPath(item));
                UpdateAssetIcon(obj, item.icon);
            });
        }

        public static List<T> FindAssetsByType<T>() where T : Object
        {
            List<T> assets = new List<T>();
            string[] guids = AssetDatabase.FindAssets(string.Format("t:{0}", typeof(T)));
            for (int i = 0; i < guids.Length; i++)
            {
                string assetPath = AssetDatabase.GUIDToAssetPath(guids*);*

T asset = AssetDatabase.LoadAssetAtPath(assetPath);
if (asset != null)
{
assets.Add(asset);
}
}
return assets;
}

public static void UpdateAssetIcon(Object asset, Sprite icon)
{
if (icon && icon.texture)
{
EditorGUIUtility.SetIconForObject(asset, icon.texture);
}
}
}
}
----------
Desired behavior:
On load, take each Item and replace its asset icon with the appropriate item icon.
Actual behavior:
On load, the icon for each item is set to whichever one was processed last.
Any idea what’s going on here?

You can’t. The icon is set on the MonoScript, so it’s shared between all instances of the same class.

You can try using RenderStaticPreview, but it has some quirks, like it doesn’t show for thumbnails in the object picker. The quirks change sometimes with the Unity Editor version. It could work for you, at least partially, depending on your use case.

Try moving the [InitializeOnLoad] attribute to the static constructor.

From the manual “Static constructors with this attribute are called when scripts in the project are recompiled” (when Unity loads, and when your scripts are recompiled).