Last active
March 24, 2025 10:27
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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