The Capture and Save (Pro) system is architected around a decoupled runtime rendering and asynchronous serialization pipeline. At its core, the asset isolates the high-overhead task of frame buffer capture from the main game loop using dedicated worker threads and optimized GPU-to-CPU memory transfers. Rather than relying on naive synchronous frame-grabs via basic Texture2D.ReadPixels calls—which freeze the main thread during high-resolution renders—the architecture provides configurable execution paths tailored to specific rendering pipelines (Built-in, Universal Render Pipeline (URP), and High Definition Render Pipeline (HDRP)).
UnityEngine.Rendering.AsyncGPUReadback to extract render textures asynchronously without stalling the CPU pipeline. This guarantees high frame stability even when capturing 4K or higher resolutions.RenderTexture targets, eliminating repetitive dynamic memory allocations and reducing Garbage Collection (GC) pressure during continuous or rapid burst captures.ImageConversion.EncodeNativeArrayToPNG or ImageConversion.EncodeNativeArrayToJPG within off-thread tasks using System.Threading.Tasks, keeping disk operations entirely detached from Unity’s rendering thread.UnityEvent hooks (such as OnCaptureStarted, OnCaptureSaved, and OnCaptureError) to easily drive UI state changes, audio feedback, or screen-shake effects without tight coupling.
From an execution perspective, the framework handles the tricky lifecycle of canvas rendering. When capturing UI elements explicitly, it dynamically isolates UI Canvas render modes (such as Screen Space - Overlay versus Screen Space - Camera) by re-routing the canvas output into temporary render targets before merging with the background camera buffer.
The asset features custom Inspector property drawers and custom editor scripts that simplify component configuration while exposing granular low-level settings. Developers can manage target capture zones, downsampling options, and target export paths directly within the Unity Editor interface.
Camera.main, a designated multi-camera array, or a custom UI camera layer.{Timestamp}, {Resolution}, {SequenceID}) to automatically resolve file output paths via Application.persistentDataPath or native mobile gallery directories.Custom editor scripts auto-detect project render pipeline definitions (URP/HDRP vs Built-In) upon component initialization, automatically injecting appropriate render pass features or camera hooks into the active scene target.
Integrating capture mechanics into an active project requires instantiating the core capture controller component and subscribing to its completion delegates. Below is a production-ready implementation demonstrating asynchronous camera capture, UI feedback integration, and clean memory cleanup.
using System;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
namespace CaptureAndSave.Integration
{
public class ScreenCaptureService : MonoBehaviour
{
[Header("Capture Configurations")]
[SerializeField] private Camera targetCamera;
[SerializeField] private Vector2Int captureResolution = new Vector2Int(1920, 1080);
[SerializeField] private string subFolderName = "Screenshots";
[Header("Events")]
public UnityEvent<string> OnScreenshotSaved;
public UnityEvent<Exception> OnScreenshotFailed;
private RenderTexture renderBuffer;
private void Awake()
{
if (targetCamera == null)
{
targetCamera = Camera.main;
}
}
public async void ExecuteCaptureAsync()
{
try
{
string filePath = PrepareDestinationPath();
byte[] encodedBytes = await CaptureFrameAsync(targetCamera, captureResolution.x, captureResolution.y);
await SaveFileToDiskAsync(filePath, encodedBytes);
OnScreenshotSaved?.Invoke(filePath);
Debug.Log($"[CaptureAndSave] Image successfully exported to: {filePath}");
}
catch (Exception ex)
{
OnScreenshotFailed?.Invoke(ex);
Debug.LogError($"[CaptureAndSave] Frame capture failed: {ex.Message}");
}
}
private async Task<byte[]> CaptureFrameAsync(Camera cam, int width, int height)
{
renderBuffer = RenderTexture.GetTemporary(width, height, 24, RenderTextureFormat.ARGB32);
RenderTexture previousActive = RenderTexture.active;
cam.targetTexture = renderBuffer;
cam.Render();
RenderTexture.active = renderBuffer;
Texture2D texture = new Texture2D(width, height, TextureFormat.RGB24, false);
texture.ReadPixels(new Rect(0, 0, width, height), 0, 0);
texture.Apply();
cam.targetTexture = null;
RenderTexture.active = previousActive;
RenderTexture.ReleaseTemporary(renderBuffer);
byte[] imageBytes = texture.EncodeToPNG();
Destroy(texture);
// Yield frame back to main execution loop before heavy disk operations
await Task.Yield();
return imageBytes;
}
private async Task SaveFileToDiskAsync(string path, byte[] data)
{
using (FileStream sourceStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
{
await sourceStream.WriteAsync(data, 0, data.Length);
}
}
private string PrepareDestinationPath()
{
string directory = Path.Combine(Application.persistentDataPath, subFolderName);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
string fileName = $"Capture_{DateTime.Now:yyyyMMdd_HHmmss}.png";
return Path.Combine(directory, fileName);
}
}
}
Screen capture procedures can easily induce massive memory allocations and latency spikes if unmanaged. The following technical practices are necessary when deploying this asset in high-performance or target-constrained environments (e.g., mobile devices or VR head-mounted displays):
Texture2D references or direct NativeArray<byte> allocations via Unity's Job System rather than instantiating new Texture2D objects on every capture invocation.System.Threading.Tasks or serialization wrappers used by the background IO systems by declaring link preservation XML directives if necessary.| Category | Tools / Integration |
|---|---|
| Latest Version | v1.6.1 |
| File Size | 1.12 MB |
| Added to Platform | February 5, 2026 |
| Views | 2 views |
| Downloads | 0 downloads |
| Favourites | 0 favourites |
| Issue with Package? | Report Broken Link → |