In-Editor Screenshot Script for Unity

This little script can take a Screenshot in custom resolution and with the option to render a transparent background. This might come in handy when you want to create renderings of in-game assets from within the Unity Editor, like characters or vehicles.

How the Screenshot Component looks in the Editor
Screenshot in the Editor

The perspective of the Screenshot is defined by a Camera component that is attached to the same GameObject. So it is possible to modify the position, rotation and focal length through the Transform of the GameObject. All of this is possible without the need to run the scene. Simply click the “Take Screenshot” button in the Inspector.

Download Screenshot Unitypackage
Download Screenshot Unitypackage

Here is the implementation:

using System;
using System.IO;
using UnityEngine;

[RequireComponent(typeof(Camera))]
public class Screenshot : MonoBehaviour {

    [SerializeField] int width = 1024;
    [SerializeField] int height = 512;
    [SerializeField] string folder = "Screenshots";
    [SerializeField] string filenamePrefix = "screenshot";
    [SerializeField] bool ensureTransparentBackground = false;


    [ContextMenu("Take Screenshot")]
    public void TakeScreenshot() {
        folder = GetSafePath(folder.Trim('/'));
        filenamePrefix = GetSafeFilename(filenamePrefix);

        string dir = Application.dataPath + "/" + folder + "/";
        string filename = filenamePrefix + "_" + DateTime.Now.ToString("yyMMdd_HHmmss") + ".png";
        string path = dir + filename;

        Camera cam = GetComponent<Camera>();

        // Create Render Texture with width and height.
        RenderTexture rt = new RenderTexture(width, height, 0, RenderTextureFormat.ARGB32);
        
        // Assign Render Texture to camera.
        cam.targetTexture = rt;

        // save current background settings of the camera
        CameraClearFlags clearFlags = cam.clearFlags;
        Color backgroundColor = cam.backgroundColor;

        // make the background transparent when enabled
        if(ensureTransparentBackground) {
            cam.clearFlags = CameraClearFlags.SolidColor;
            cam.backgroundColor = new Color(); // alpha is zero
        }

        // Render the camera's view to the Target Texture.
        cam.Render();

        // restore the camera's background settings if they were changed before rendering
        if(ensureTransparentBackground) {
            cam.clearFlags = clearFlags;
            cam.backgroundColor = backgroundColor;
        }

        // Save the currently active Render Texture so we can override it.
        RenderTexture currentRT = RenderTexture.active;

        // ReadPixels reads from the active Render Texture.
        RenderTexture.active = cam.targetTexture;

        // Make a new texture and read the active Render Texture into it.
        Texture2D screenshot = new Texture2D(width, height, TextureFormat.ARGB32, false);
        screenshot.ReadPixels(new Rect(0, 0, width, height), 0, 0, false);

        // PNGs should be sRGB so convert to sRGB color space when rendering in linear.
        if(QualitySettings.activeColorSpace == ColorSpace.Linear) {
            Color[] pixels = screenshot.GetPixels();
            for(int p = 0; p < pixels.Length; p++) {
                pixels[p] = pixels[p].gamma;
            }
            screenshot.SetPixels(pixels);
        }

        // Apply the changes to the screenshot texture.
        screenshot.Apply(false);

        // Save the screnshot.
        Directory.CreateDirectory(dir);
        byte[] png = screenshot.EncodeToPNG();
        File.WriteAllBytes(path, png);

        // Remove the reference to the Target Texture so our Render Texture is garbage collected.
        cam.targetTexture = null;

        // Replace the original active Render Texture.
        RenderTexture.active = currentRT;

        Debug.Log("Screenshot saved to:\n" + path);
    }

    public string GetSafePath(string path) {
        return string.Join("_", path.Split(Path.GetInvalidPathChars()));
    }

    public string GetSafeFilename(string filename) {
        return string.Join("_", filename.Split(Path.GetInvalidFileNameChars()));
    }
}

And the Editor script to show the “Take Screenshot” button in addition to the context menu entry:

using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(Screenshot))]
public class ScreenshotEditor : Editor {

    public override void OnInspectorGUI() {
        DrawDefaultInspector();

        if(GUILayout.Button("Take Screenshot")) {
            ((Screenshot)serializedObject.targetObject).TakeScreenshot();
        }
    }
}

Make sure the ScreenshotEditor is saved to a folder named “Editor” since it is using the UnityEditor assembly. Or simply download the Unitypackage.

Download Screenshot Unitypackage
Download Screenshot Unitypackage

Feel free to copy and adjust the code to your needs. Please write a comment and tell me what you think or when there is something I could improve!

Published by

Chris

Christian Kauppert is CTO & Head of XR Engineering at MSM.digital AR / VR Labs. Before he worked as a freelance Unity developer and VFX compositor for over 9 years. He uses this blog to show and write about selected works. Occasionally Chris also writes about issues and solutions he stumbles upon while developing interactive experiences and XR applications.

9 thoughts on “In-Editor Screenshot Script for Unity”

  1. Hey, thanks a lot for this script. It works really well in Unity editor. I just want to know whether it will work on HoloLens 2 to capture the holograms. I am working on Microsoft hololens 2 so asking this. Do you have any idea about it?

    1. Hey Ruchir, Thank you for your message! I wrote the script to make fast screenshots of assets in the Editor. I haven’t tested it on HoloLens, but you could try to call the `TakeScreenshot` function during runtime, for example via button press.

  2. Hi,
    neat script, though I had to change the “depth” of the render texture from “0” to 24 and disable the linear gamma correction. I am using URP and linear color space, no depth texture. Just wanted to let you know. Do you have a github repo for this to send push requests to?

    Anyhow, thanks for this little helper.

    1. Hi Geo,

      I am so sorry! Somehow this comment slipped through and I didn’t approve it for such a long time! :/

      Anyways, better late than never. Thanks a lot for your feedback! There’s currently no repo, but I like the idea! I will try to look at the changes you stated manually the next days and make an update if it’s still applicable with the new versions of Unity.

      Sorry and thanks again!
      Chris

    1. Hi Gökdeniz,

      Thanks for your comment. It is not really meant to capture UI. I made it to create transparent screenshots within the Editor. But feel free to adjust it to your needs. There should be a way to capture UI as well.

      And if you want to take a normal screenshot during runtime, simply use CaptureScreenshot.

      I hope that helps.
      Chris

Leave a Reply

Your email address will not be published. Required fields are marked *