Hey guys, i doing some itens for my game make the development easer, i wish add custom icons to my itens, which are ScriptableObjects, how i can do this? i know the trick of put the icon on Gizmo folder with the same name as the script, but the icons should be different for different itens which have the same script
Hi there @Conley. You can do it without the Gizmos folder. Just select the ScriptableObject script (not the ScriptableObject asset!) and select its icon in the Inspector. That will change that script’s icon as well as all icons of respective ScriptableObject assets!
Additionally, you can visit this thread for more info, it has lots of gold in it: https://forum.unity.com/threads/custom-scriptableobject-icons-thumbnail.256246/
Hi, i’m working on a cards game where there are different “roles”. Every scriptable object needs to have a custom image. How do i do it?
Add an 'image' property. From your game, load it into the UI.
– InvigorateLooks like there's a new API for this in 2021.2! https://docs.unity.cn/2021.2/Documentation/ScriptReference/EditorGUIUtility.SetIconForObject.html
– TunicThere is a new API for this in 2021.2 that might do what you are looking for. It even tells you how to make it persistent across script reloads
Edit: Okay so it turns out this is really really jank. As far as I can tell, Unity doesn’t want you to instance these icons. On compile/load, all of the assets will be set to the same icon, even if you properly set each one individually. You have to inspect them by clicking on them individually to get them to update to their true icons. If anyone has a solution to this please let me know
Set fractionofjourney yo 0 ya te start. Smooth speed Is a constant? The code was untested but seems fine to me, ill test it tommorrow
– TricksterHi.
It’s possible!
Short history:
I downloaded and explore this project:
I noticed that in this project, icons from scriptable objects are displayed in the inspector:
After, i found some editor script, and edited him for my project.
I don’t understand how it works, but it works. =)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
using System.Reflection;
using Object = UnityEngine.Object;
[CustomEditor(typeof(item_so),true)]
[CanEditMultipleObjects]
public class ItemSOEditor : Editor
{
private item_so item { get { return (target as item_so); } }
public override Texture2D RenderStaticPreview(string assetPath,Object[] subAssets,int width,int height)
{
if(item.standart_item_struct.item_icon!=null)
{
Type t = GetType("UnityEditor.SpriteUtility");
if(t!=null)
{
MethodInfo method = t.GetMethod("RenderStaticPreview",new Type[] { typeof(Sprite),typeof(Color),typeof(int),typeof(int) });
if(method!=null)
{
object ret = method.Invoke("RenderStaticPreview",new object[] { item.standart_item_struct.item_icon,Color.white,width,height });
if(ret is Texture2D)
return ret as Texture2D;
}
}
}
return base.RenderStaticPreview(assetPath,subAssets,width,height);
}
private static Type GetType(string TypeName)
{
var type = Type.GetType(TypeName);
if(type!=null)
return type;
if(TypeName.Contains("."))
{
var assemblyName = TypeName.Substring(0,TypeName.IndexOf('.'));
var assembly = Assembly.Load(assemblyName);
if(assembly==null)
return null;
type=assembly.GetType(TypeName);
if(type!=null)
return type;
}
var currentAssembly = Assembly.GetExecutingAssembly();
var referencedAssemblies = currentAssembly.GetReferencedAssemblies();
foreach(var assemblyName in referencedAssemblies)
{
var assembly = Assembly.Load(assemblyName);
if(assembly!=null)
{
type=assembly.GetType(TypeName);
if(type!=null)
return type;
}
}
return null;
}
}
My friend, your solution is exactly what I was looking for, and has worked flawlessly for adding custom icons to ScriptableObject assets.
– KazachokThis almost works perfect except for the fact that really tiny sprites (like 8x8) appear very small. Is there a way to scale it up? Simply changing the width and height does not work
– Jackofalltradesif your current Unity version doesn’t publicly expose EditorGUIUtility.SetIconForObject…
here’s a utility window that makes use of the same API using Reflection:
using System.Reflection;
using UnityEditor;
using UnityEngine;
internal class EditorGUIUtilityInternals : EditorWindow
{
private MethodInfo setIcon, getIcon, copyIcon;
private Texture2D icon;
private Object target;
private bool hasIcon;
[MenuItem("EditorGUIUtility/Internals/SetIconForObject")]
private static void GetWindow()
{
var rect = new Rect(Screen.width/2F, Screen.height/2F, 350F, 130F);
const string title = "EditorGUIUtility Internals";
GetWindowWithRect<EditorGUIUtilityInternals>(rect, true, title, true).ShowUtility();
}
private void OnEnable()
{
const BindingFlags bindings = BindingFlags.NonPublic | BindingFlags.Static;
var utility = typeof(EditorGUIUtility);
setIcon = utility.GetMethod("SetIconForObject", bindings);
getIcon = utility.GetMethod("GetIconForObject", bindings);
copyIcon = typeof(MonoImporter).GetMethod("CopyMonoScriptIconToImporters", bindings);
}
private void OnGUI()
{
EditorGUI.BeginChangeCheck();
target = EditorGUILayout.ObjectField("Target Object", target, typeof(Object), true);
if (target && EditorGUI.EndChangeCheck()) RefreshHasIcon();
EditorGUILayout.Space(EditorGUIUtility.singleLineHeight);
icon = (Texture2D)EditorGUILayout.ObjectField("Icon", icon, typeof(Texture2D), false);
EditorGUILayout.BeginHorizontal();
{
GUI.enabled = target && icon;
if (GUILayout.Button("Set Icon For Target"))
SetOrRemoveIconForObject(icon); // Assign
GUI.enabled = hasIcon;
if (GUILayout.Button("Remove Icon From Target"))
SetOrRemoveIconForObject(); // Unset
}
EditorGUILayout.EndHorizontal();
}
private void SetOrRemoveIconForObject(Texture2D texture = null)
{
var message = texture == null
? $"{target.name}'s Icon is About to be Unbound from"
: $"{icon.name} is About to be Bound to {target.name}";
if (EditorUtility.DisplayDialog(titleContent.text, message, "Gotcha!", "Nope..."))
{
setIcon?.Invoke(null, new[] { target, texture });
var targetPath = AssetDatabase.GetAssetPath(target);
var importer = (MonoImporter)AssetImporter.GetAtPath(targetPath);
_ = copyIcon?.Invoke(null, new[] { importer.GetScript() });
importer.SaveAndReimport();
RefreshHasIcon();
}
}
private void RefreshHasIcon()
{
var tempIcon = (Texture2D)getIcon?.Invoke(null, new[] { target });
hasIcon = tempIcon != null;
}
}
how to display the utility and a preview of:
Use EditorGUIUtility.SetIconForObject is just working. Just do somethin like this:
[CreateAssetMenu(fileName = "NewCustomScriptableObject", menuName = "YourMenu/CustomScriptableObject")]
public class TestSO : ScriptableObject
{
public int A;
private void OnEnable()
{
Texture2D icon = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Games/Gizmos/TestSO Icon.png");
EditorGUIUtility.SetIconForObject(this, icon);
}
}
and whenever you create a SO asset then it’ll show up with custom icon.
© 2022 - 2024 — McMap. All rights reserved.
Hi, i'm working on a cards game where there are different "roles". Every scriptable object needs to have a custom image. How do i do it?
– InvigorateIm not understanding this?
– RoiceThis works. However, existing instances of the ScriptableObject were not updated (i.e. it only applied to the ScriptableObject assets I created after changing the icon). Didn't try restarting Unity though, so that may fix that issue.
– DiffusiveCan confirm, restarting Unity fixes existing ScriptableObject icons. Tested on 2022.3.12f1.
– Psychotechnology