Skip to content

Instantly share code, notes, and snippets.

@chrisyarbrough
Last active March 24, 2025 10:27
Show Gist options
  • Save chrisyarbrough/52ecc71c616614231e3fc0aacde0c08a to your computer and use it in GitHub Desktop.
Save chrisyarbrough/52ecc71c616614231e3fc0aacde0c08a to your computer and use it in GitHub Desktop.
This shows how UnityEditor.PreviewRenderUtility can be used to draw a custom scene and render it interactively in an editor window. The target object can be modified while running, but it is important to note, that in this case we need to managed target instantiation and destruction ourselves.
using UnityEditor;
using UnityEngine;
/// <summary>
/// Demonstrates how to use <see cref="UnityEditor.PreviewRenderUtility"/>
/// to render a small interactive scene in a custom editor window.
/// </summary>
public class CustomPreviewExample : EditorWindow
{
[MenuItem("My Tools/Custom Preview")]
public static void ShowWindow()
{
GetWindow<CustomPreviewExample>("Preview");
}
private PreviewRenderUtility previewUtility;
private GameObject targetObject;
private void OnEnable()
{
previewUtility = new PreviewRenderUtility();
SetupPreviewScene();
}
private void OnDisable()
{
if (previewUtility != null)
previewUtility.Cleanup();
if (targetObject != null)
Object.DestroyImmediate(targetObject);
}
private void SetupPreviewScene()
{
targetObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
targetObject.transform.position = Vector3.zero;
// Since we want to manage this instance ourselves, hide it
// from the current active scene, but remember to also destroy it.
targetObject.hideFlags = HideFlags.HideAndDontSave;
previewUtility.AddSingleGO(targetObject);
// Camera is spawned at origin, so position is in front of the cube.
previewUtility.camera.transform.position = new Vector3(0f, 0f, -10f);
// This is usually set very small for good performance, but
// we need to shift the range to something our cube can fit between.
previewUtility.camera.nearClipPlane = 5f;
previewUtility.camera.farClipPlane = 20f;
}
private void Update()
{
// Just do some random modifications here.
float time = (float)EditorApplication.timeSinceStartup * 15;
targetObject.transform.rotation = Quaternion.Euler(time * 2f, time * 4f, time * 3f);
// Since this is the most important window in the editor, let's use our
// resources to make this nice and smooth, even when running in the background.
Repaint();
}
private void OnGUI()
{
// Render the preview scene into a texture and stick it
// onto the current editor window. It'll behave like a custom game view.
Rect rect = new Rect(0, 0, base.position.width, base.position.height);
previewUtility.BeginPreview(rect, previewBackground: GUIStyle.none);
previewUtility.Render();
var texture = previewUtility.EndPreview();
GUI.DrawTexture(rect, texture);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment