Skip to content

Instantly share code, notes, and snippets.

@maoyeedy
Last active April 29, 2025 20:15
Show Gist options
  • Save maoyeedy/6e16e18ee3d9b31d657a972e87c3debf to your computer and use it in GitHub Desktop.
Save maoyeedy/6e16e18ee3d9b31d657a972e87c3debf to your computer and use it in GitHub Desktop.
[Unity] Advanced Screenshot Recorder
#if UNITY_EDITOR
using System;
using System.IO;
using UnityEditor;
using UnityEditor.Recorder;
using UnityEditor.Recorder.Input;
using UnityEngine;
using UnityEngine.InputSystem;
namespace Screenshot
{
/// <summary>
/// Utilizes Unity Recorder for custom resolutions.
/// To take screenshot with it, add this component to a GameObject.
/// </summary>
public class ScreenshotRecorder : MonoBehaviour
{
[Header("Input Settings")]
// You may customize more key bindings, including gamepads, mouse clicks...
public InputAction Input = new(
"Screenshot Keyboard",
InputActionType.Button,
"<Keyboard>/f12");
[Header("Path Settings")]
public string Prefix = "Screenshot";
[SerializeField]
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.FolderPath]
#endif
public string Folder = "Recordings";
[Header("Output Settings")]
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.HideLabel]
#endif
public FormatSettings Format = new();
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.HideLabel]
#endif
public ResolutionSettings Resolution = new();
[Header("Recorder Settings")]
private RecorderController _recorderController;
private RecorderControllerSettings _controllerSettings;
private ImageRecorderSettings _imageRecorder;
private void OnEnable()
{
// Setup Recording
_imageRecorder = ScriptableObject.CreateInstance<ImageRecorderSettings>();
_controllerSettings = ScriptableObject.CreateInstance<RecorderControllerSettings>();
_controllerSettings.AddRecorderSettings(_imageRecorder);
_controllerSettings.SetRecordModeToSingleFrame(0);
_recorderController = new RecorderController(_controllerSettings);
// Setup Input
Input.performed += OnScreenshotPerformed;
Input.Enable();
}
private void OnDisable()
{
Input.Disable();
Input.performed -= OnScreenshotPerformed;
}
private void OnScreenshotPerformed(InputAction.CallbackContext context)
{
CaptureScreenshot();
}
private string GetFileNameWithTimeStamp()
{
var timestamp = DateTime.Now.ToString("yyMMdd_HHmmss");
var fileName = $"{Prefix}_{timestamp}";
return fileName;
}
private string GetFileFullPath(string fileName)
{
var mediaOutputFolder = Path.Combine(Application.dataPath, "..", Folder);
if (!Directory.Exists(mediaOutputFolder)) Directory.CreateDirectory(mediaOutputFolder);
var fullPath = Path.Combine(mediaOutputFolder, fileName);
return fullPath;
}
private void CaptureScreenshot()
{
var resolution = Resolution.GetDimensions();
_imageRecorder.OutputFormat = Format.GetFormat();
_imageRecorder.CaptureAlpha = Format.CaptureAlpha;
_imageRecorder.JpegQuality = Format.JpegQuality;
_imageRecorder.imageInputSettings = new GameViewInputSettings
{
OutputWidth = resolution.x, OutputHeight = resolution.y
};
var fileName = GetFileNameWithTimeStamp();
var fullPath = GetFileFullPath(fileName);
_imageRecorder.OutputFile = fullPath;
_recorderController.PrepareRecording();
_recorderController.StartRecording();
Debug.Log($"{fileName}.{Format.GetFormat()} captured at {resolution.x}x{resolution.y}", this);
}
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.Button]
#endif
private void OpenScreenshotsFolder()
{
var mediaOutputFolder = Path.Combine(Application.dataPath, "..", Folder);
if (!Directory.Exists(mediaOutputFolder)) Directory.CreateDirectory(mediaOutputFolder);
EditorUtility.RevealInFinder(mediaOutputFolder + "/");
}
}
[Serializable]
public class FormatSettings
{
private enum Format
{
PNG = 0,
JPG = 1,
}
[SerializeField]
private Format _format = Format.PNG;
public ImageRecorderSettings.ImageRecorderOutputFormat GetFormat()
{
return _format switch
{
Format.PNG => ImageRecorderSettings.ImageRecorderOutputFormat.PNG,
Format.JPG => ImageRecorderSettings.ImageRecorderOutputFormat.JPEG,
_ => ImageRecorderSettings.ImageRecorderOutputFormat.PNG
};
}
private bool IsPNG => _format == Format.PNG;
private bool IsJPG => _format == Format.JPG;
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.ShowIf(nameof(IsPNG))]
#endif
public bool CaptureAlpha = false;
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.ShowIf(nameof(IsJPG))]
#endif
[Range(0, 100)]
public int JpegQuality = 75;
}
[Serializable]
public class ResolutionSettings
{
private enum Resolution
{
HD = 0,
FHD = 1,
QHD = 2,
UHD = 3,
Custom = 4
}
[SerializeField]
private Resolution _resolution = Resolution.FHD;
private bool UseCustomResolution => _resolution == Resolution.Custom;
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.ShowIf(nameof(UseCustomResolution))]
[Sirenix.OdinInspector.HideLabel]
#endif
[SerializeField]
private Vector2Int _customResolution = new(1920, 1080);
public Vector2Int GetDimensions()
{
if (UseCustomResolution)
{
return _customResolution;
}
return _resolution switch
{
Resolution.HD => new Vector2Int(1280, 720),
Resolution.FHD => new Vector2Int(1920, 1080),
Resolution.QHD => new Vector2Int(2560, 1440),
Resolution.UHD => new Vector2Int(3840, 2160),
_ => new Vector2Int(1920, 1080)
};
}
}
}
#endif
@maoyeedy
Copy link
Author

maoyeedy commented Apr 29, 2025

preview

The default screenshot key is F12, you may bind gamepad buttons to it also.

@maoyeedy
Copy link
Author

maoyeedy commented Apr 29, 2025

Diklae
This script was originally made for https://maoyeedy.itch.io/ruby-ran-away-from-home

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment