I want to capture a screenshot from a custom EditorWindow that I'm using as a LevelEditor for a game I'm working on, but i'm not sure on how to do it.
What I want is to capture the EditorWindow, NOT the game view or the scene view.
Can you help me? Thanks!
Edit: I want to take screenshots by code, when pressing a GUILayout.Button :)
I made a script for this using InternalEditorUtility.ReadScreenPixel
.
At first I actually had it as you requested on a GUILayout.Button
but decided to instead provide a more general solution here which is completely independent from the EditorWindow
itself.
(You could still call EditorScreenshotExtension.Screenshot();
from the GUILayout.Button
anyway.)
I rather added a global MenuItem
with ShortCut so you actually can take a screenshot of any currently active (last clicked/focused) EditorWindow
!
EditorScreenshotExtension.cs
using System.IO;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
public static class EditorScreenshotExtension
{
[MenuItem("Screenshot/Take Screenshot %#k")]
private static void Screenshot()
{
// Get actvive EditorWindow
var activeWindow = EditorWindow.focusedWindow;
// Get screen position and sizes
var vec2Position = activeWindow.position.position;
var sizeX = activeWindow.position.width;
var sizeY = activeWindow.position.height;
// Take Screenshot at given position sizes
var colors = InternalEditorUtility.ReadScreenPixel(vec2Position, (int)sizeX, (int)sizeY);
// write result Color[] data into a temporal Texture2D
var result = new Texture2D((int)sizeX, (int)sizeY);
result.SetPixels(colors);
// encode the Texture2D to a PNG
// you might want to change this to JPG for way less file size but slightly worse quality
// if you do don't forget to also change the file extension below
var bytes = result.EncodeToPNG();
// In order to avoid bloading Texture2D into memory destroy it
Object.DestroyImmediate(result);
// finally write the file e.g. to the StreamingAssets folder
var timestamp = System.DateTime.Now;
var stampString = string.Format("_{0}-{1:00}-{2:00}_{3:00}-{4:00}-{5:00}", timestamp.Year, timestamp.Month, timestamp.Day, timestamp.Hour, timestamp.Minute, timestamp.Second);
File.WriteAllBytes(Path.Combine(Application.streamingAssetsPath, "Screenshot" + stampString + ".png"), bytes);
// Refresh the AssetsDatabase so the file actually appears in Unity
AssetDatabase.Refresh();
Debug.Log("New Screenshot taken");
}
}
Since it uses UnityEditor
and UnityEditorInternal
make sure to place it in a folder called Editor
to exlude it from any builds.
After importing it to your project simply use CTRL + SHIFT + K to create a Screenshot of the currently active EditorWindow.
Screenshots are placed as PNG file in Assets/StreamingAssets
with a timestamp in the name.
It will also add an entry to the top menu of the UniytEditor.
The current shortcut was just a random one which is not used so far. you can change it in [MenuItem(Screenshot/Take Screenshot %#k)]
following the MenuItem docs
To create a hotkey you can use the following special characters:
- % (ctrl on Windows, cmd on macOS)
- # (shift)
- & (alt)
- If no special modifier key combinations are required the key can be given after an underscore.
For example to create a menu with hotkey shift-alt-g use "MyMenu/Do Something #&g". To create a menu with hotkey g and no key modifiers pressed use _ like "MyMenu/Do Something _g".
Some special keyboard keys are supported as hotkeys, for example "#LEFT" would map to shift-left. The keys supported like this are: LEFT, RIGHT, UP, DOWN, F1 .. F12, HOME, END, PGUP, PGDN.
A hotkey text must be preceded with a space character ("MyMenu/Do_g" won't be interpreted as hotkey, while "MyMenu/Do _g" will).
Here in action - the first time I simply press CTRL + SHIFT + K after having focused the Project
view last; the second time I focus the Inspector
and use the menu item to take the screenshot