How can I create a texture/sprite field in Inspector like this?

I want to create a property like this:
2276976--152801--Untitled-1.png

using a PropertyDrawer. Can you help me?

This is what I have so far:

[CustomPropertyDrawer(typeof(CombinableSpritesAttribute))]
public class CombinableSpritesAttributeEditor: PropertyDrawer
{
    public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
    {
        var ident = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;
  
        var spriteRect = new Rect(position.x + x, position.y + y, position.width, position.height);
  
        property.objectReferenceValue =
            EditorGUI.ObjectField(spriteRect, property.objectReferenceValue, typeof(Sprite), false);

        EditorGUI.indentLevel = ident;
    }

    public override float GetPropertyHeight (SerializedProperty property, GUIContent label)
    {
        return base.GetPropertyHeight(property, label) + 50f;
    }
}

But the sprite is not rendered properly, the field stays blank (dark color as if empty):

2276976--152809--Capturar.PNG

If I scroll the Inspector, the preview image blinks inside that box…

3 Likes

I think you are wanting the ObjectField to be of type Texture2D instead of a Sprite.

Just try this:

property.objectReferenceValue = EditorGUI.ObjectField(spriteRect, property.objectReferenceValue, typeof(Texture2D), false);

Couldn’t get scriptableobject sprites to draw consistently in a property drawer. The default EditorGUI.ObjectField when large enough to show the icon would randomly flicker the sprite and render it with a delay after clicking in the inspector panel.

Between this thread and Drawing a texture in a custom PropertyDrawer - Questions & Answers - Unity Discussions I finally got a working solution.

In the end I changed the height of the ObjectField so the default icon is not drawn and use a GUIStyle to render the sprite as a background. Using this method I can mash the arrow key down through my scriptableobjects and the sprites show instantly with now weirdness in the inspector.

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

[CustomPropertyDrawer(typeof(Sprite))]
public class SpriteDrawer : PropertyDrawer {

    private static GUIStyle s_TempStyle = new GUIStyle();
 
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {                                     
        var ident = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        Rect spriteRect;
     
        //create object field for the sprite
        spriteRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
        property.objectReferenceValue = EditorGUI.ObjectField(spriteRect, property.name, property.objectReferenceValue, typeof(Sprite), false);

        //if this is not a repain or the property is null exit now
        if (Event.current.type != EventType.Repaint || property.objectReferenceValue == null)
            return;

        //draw a sprite
        Sprite sp = property.objectReferenceValue as Sprite;

        spriteRect.y += EditorGUIUtility.singleLineHeight+4;
        spriteRect.width = 64;
        spriteRect.height = 64;     
        s_TempStyle.normal.background = sp.texture;
        s_TempStyle.Draw(spriteRect, GUIContent.none, false, false, false, false);
             
        EditorGUI.indentLevel = ident;
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return base.GetPropertyHeight(property, label) + 70f;
    }
}
5 Likes

Your code error if using to choose 2 image at the same time, the image is change same

2 Likes

Quick workaround: disable multi editing by pasting the following code on top of the OnGUI (public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)) method:

if (property.serializedObject.isEditingMultipleObjects)
{
    GUI.Label(position, "Sprite multiediting not supported");
    return;
}