Class UnityAchievementScreenshotCapturer
Grabs the frame the player unlocked an achievement on, downscales it to the width the project keeps, and hands back the encoded PNG bytes.
Implements
Namespace: Serenity.Achievements.Infrastructure.Components
Assembly: Serenity.UnityAchievements.Infrastructure.dll
Syntax
public class UnityAchievementScreenshotCapturer : MonoBehaviour, IAchievementScreenshotCapturer
Remarks
A frame can only be read back at the end of a rendered frame, which no await can
reach directly, so a request is parked as a TaskCompletionSource<TResult> and
completed by a coroutine that yields on UnityEngine.WaitForEndOfFrame. The unlock path
never waits on this — it detaches the whole capture — so at most one frame of latency is
invisible to it.
Requests that arrive while a capture is in flight are coalesced: they all resolve to the same bytes. Two achievements unlocking in the same frame earned the same moment, and a second full-screen readback would cost a stall to produce a duplicate image.
The pending list is taken under a lock and the capture itself is started from
Serenity.Achievements.Infrastructure.Components.UnityAchievementScreenshotCapturer.Update rather than from the request: the unlock path is asynchronous and a
store adapter is free to resume it on a background thread, where StartCoroutine is
not callable at all.
Nothing here throws at the caller, and nothing is left waiting. A disabled capturer, a headless run, a readback the platform refuses, an end of frame that never arrives and a destroyed component all end the same way: null bytes, a warning, and an unlock that stands without a screenshot.
Constructors
UnityAchievementScreenshotCapturer()
Declaration
public UnityAchievementScreenshotCapturer()
Properties
IsEnabled
Declaration
public bool IsEnabled { get; }
Property Value
| Type | Description |
|---|---|
| bool |
Remarks
False wherever no frame is ever presented — outside play mode, in batch mode, and on a build with no graphics device. A frame that was never rendered cannot be read back, and reporting the truth here means the attachment skips capture entirely instead of parking one request per unlock behind an end of frame that never comes.
Methods
Create(int, ILogService)
Creates the capturer on its own persistent GameObject.
Declaration
public static UnityAchievementScreenshotCapturer Create(int maximumWidth, ILogService logService)
Parameters
| Type | Name | Description |
|---|---|---|
| int | maximumWidth | The width a captured frame is downscaled to. Zero or less keeps the frame as captured. |
| ILogService | logService | Logging service. May be |
Returns
| Type | Description |
|---|---|
| UnityAchievementScreenshotCapturer | The created capturer. |
Remarks
An earlier capturer, if any, is destroyed first — one host, one pending queue.
TryCaptureAsync(CancellationToken)
Declaration
public Task<byte[]> TryCaptureAsync(CancellationToken cancellationToken)
Parameters
| Type | Name | Description |
|---|---|---|
| CancellationToken | cancellationToken |
Returns
| Type | Description |
|---|---|
| Task<byte[]> |