Unity sets previews and thumbnails for prefabrications

Keywords: Unity

Preview: Displayed below Inspector panel

Thumbnails: Displayed in Project View

Sometimes it's inconvenient not to have previews and thumbnails. Especially prefabricated.

Selection of several options:

1. Inheritance of ObjectPreview class

using UnityEngine;
using UnityEditor;

[CustomPreview(typeof(GameObject))]
public class MyPreview : ObjectPreview
{
    public override bool HasPreviewGUI()
    {
        return true;
    }

    public override void OnPreviewGUI(Rect r, GUIStyle background)
    {
        GUI.Label(r, target.name + " is being previewed");
    }
}

This scheme can only draw previews, not thumbnails.

 

2. Inherit the Editor class and override two methods


public Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height);

public void OnPreviewGUI(Rect r, GUIStyle background);

This method allows you to customize thumbnails and previews, but official documents indicate that:

Note: Inspector previews are limited to the primary editor of persistent objects (assets), e.g., GameObjectInspector, MaterialEditor, TextureInspector. This means that it is currently not possible for a component to have its own inspector preview.

Generally speaking, only specific types of objects are needed to generate previews. For other types of objects, use the preview scheme that comes with the system. If the target of Editor is GameObject, all previews will be affected: including models, maps, etc.

If you can inherit the default implementation of Editor, you can also achieve the goal. The key issue is that Unity is not publicly available internally. The Editor implemented inside Unity is called GameObjectInspector

Finally, the solution is to use reflection to capture the internal GameObject Inspector to handle the default preview generation scheme.

 

Two classes need to be implemented:

Preview

PreviewEditor

Usage: Add the Preview component to the required object, and set the preview and thumbnail in the Inspector panel.

Preview class:

using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
using DG.Tweening;

//Hang up this script to preview the public interface
public class Preview : MonoBehaviour {

#if UNITY_EDITOR
    public Texture2D PreviewThumbnail;
    public Texture2D PreviewImage;
#endif
}

PreviewEditor class:

using UnityEngine;
using System.Collections;
using UnityEditor;
using System.IO;
using System.Reflection;
using System.Linq;

[CustomEditor(typeof(GameObject))]
public class PreviewEditor : Editor
{
    Editor reflectorGameObjectEditor;

    private static Assembly editorAssembly = Assembly.GetAssembly(typeof(Editor));
    private static System.Type decoratedEditorType;
    void CheckReflectionEditor()
    {
        if(reflectorGameObjectEditor == null)
        {
            if(decoratedEditorType == null)
                decoratedEditorType = editorAssembly.GetTypes().Where(t => t.Name == "GameObjectInspector").FirstOrDefault();

            reflectorGameObjectEditor = Editor.CreateEditor(target, decoratedEditorType);
        }
    }

    public override bool HasPreviewGUI()
    {
        CheckReflectionEditor();

        GameObject targetGameObject = target as GameObject;

        Preview example = targetGameObject.GetComponent<Preview>();

        if (example == null || example.PreviewImage == null)
            return reflectorGameObjectEditor.HasPreviewGUI();
        
        return true;
    }

    public override void OnPreviewGUI(Rect r, GUIStyle background)
    {
        CheckReflectionEditor();

        var targetGameObject = target as GameObject;
        Preview example = targetGameObject.GetComponent<Preview>();

        if (example == null || example.PreviewImage == null)
        {
            reflectorGameObjectEditor.OnPreviewGUI(r, background);
            return;
        }
            

        GUI.DrawTexture(r, example.PreviewImage);
    }

    public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height)
    {
        CheckReflectionEditor();

        GameObject argetGameObject = target as GameObject;
        if (argetGameObject == null)
            return reflectorGameObjectEditor.RenderStaticPreview(assetPath, subAssets, width, height);

        Preview example = argetGameObject.GetComponent<Preview>();

        if (example == null || example.PreviewThumbnail == null)
            return reflectorGameObjectEditor.RenderStaticPreview(assetPath, subAssets, width, height);

        //example.PreviewIcon must be a supported format: ARGB32, RGBA32, RGB24,
        // Alpha8 or one of float formats
        Texture2D tex = new Texture2D(width, height);
        EditorUtility.CopySerialized(example.PreviewThumbnail, tex);

        return tex;
    }
}

 

Effects (showing a preview of UGUI prefabrications):

Posted by methodman on Mon, 08 Apr 2019 15:21:31 -0700