@@ -81,6 +81,18 @@ public static bool IsScreenCaptureModuleAvailable
8181 }
8282 }
8383
84+ /// <summary>
85+ /// Reflective invocation of ScreenCapture.CaptureScreenshotAsTexture(int). Returns
86+ /// null when the Screen Capture module is disabled. Centralised so the only direct
87+ /// reference to ScreenCapture lives here.
88+ /// </summary>
89+ internal static Texture2D InvokeCaptureScreenshotAsTexture ( int superSize )
90+ {
91+ if ( ! IsScreenCaptureModuleAvailable || s_captureScreenshotAsTextureMethod == null )
92+ return null ;
93+ return s_captureScreenshotAsTextureMethod . Invoke ( null , new object [ ] { superSize } ) as Texture2D ;
94+ }
95+
8496 /// <summary>
8597 /// Error message to display when Screen Capture module is not available.
8698 /// </summary>
@@ -239,6 +251,35 @@ public static ScreenshotCaptureResult CaptureFromCameraToProjectFolder(
239251 return result ;
240252 }
241253
254+ #if UNITY_EDITOR
255+ // Synchronously drive a WaitForEndOfFrame ScreenshotCapturer by pumping the editor's
256+ // player loop. Play-mode only; EditorApplication.Step is a no-op in edit mode.
257+ private static Texture2D CaptureCompositedAfterFrame ( int superSize , int timeoutSteps = 5 )
258+ {
259+ Texture2D result = null ;
260+ bool done = false ;
261+ bool callerReturned = false ;
262+ ScreenshotCapturer . Begin ( superSize , tex =>
263+ {
264+ // Late completion after the spin loop timed out: caller will never consume
265+ // the texture, so destroy it here to avoid leaking a Unity object.
266+ if ( callerReturned )
267+ {
268+ if ( tex != null ) DestroyTexture ( tex ) ;
269+ return ;
270+ }
271+ result = tex ;
272+ done = true ;
273+ } ) ;
274+ for ( int i = 0 ; i < timeoutSteps && ! done ; i ++ )
275+ {
276+ UnityEditor . EditorApplication . Step ( ) ;
277+ }
278+ callerReturned = true ;
279+ return result ;
280+ }
281+ #endif
282+
242283 /// <summary>
243284 /// Captures a screenshot using ScreenCapture.CaptureScreenshotAsTexture, which captures the
244285 /// final composited frame including UI Toolkit overlays, post-processing, etc.
@@ -269,9 +310,15 @@ public static ScreenshotCaptureResult CaptureComposited(
269310 int imgW = 0 , imgH = 0 ;
270311 try
271312 {
272- // Reflective call to ScreenCapture.CaptureScreenshotAsTexture so the file compiles
273- // even when the Screen Capture module (com.unity.modules.screencapture) is disabled.
274- tex = s_captureScreenshotAsTextureMethod . Invoke ( null , new object [ ] { result . SuperSize } ) as Texture2D ;
313+ #if UNITY_EDITOR
314+ // In play mode, inline ScreenCapture reads a backbuffer before UITK has
315+ // composited; route through WaitForEndOfFrame instead.
316+ tex = Application . isPlaying
317+ ? CaptureCompositedAfterFrame ( result . SuperSize )
318+ : InvokeCaptureScreenshotAsTexture ( result . SuperSize ) ;
319+ #else
320+ tex = InvokeCaptureScreenshotAsTexture ( result . SuperSize ) ;
321+ #endif
275322 if ( tex == null )
276323 {
277324 // Fallback to camera-based if ScreenCapture fails
@@ -787,4 +834,33 @@ private static string GetProjectRootPath()
787834 return root ;
788835 }
789836 }
837+
838+ /// <summary>
839+ /// Transient MonoBehaviour that yields WaitForEndOfFrame, calls
840+ /// ScreenCapture.CaptureScreenshotAsTexture, invokes the callback, and self-destructs.
841+ /// </summary>
842+ public sealed class ScreenshotCapturer : MonoBehaviour
843+ {
844+ private int _superSize = 1 ;
845+ private Action < Texture2D > _onComplete ;
846+
847+ /// <summary>Spawns a hidden GameObject, attaches a capturer, returns immediately.</summary>
848+ public static void Begin ( int superSize , Action < Texture2D > onComplete )
849+ {
850+ var go = new GameObject ( "__MCP_ScreenshotCapturer__" ) { hideFlags = HideFlags . HideAndDontSave } ;
851+ var c = go . AddComponent < ScreenshotCapturer > ( ) ;
852+ c . _superSize = Mathf . Max ( 1 , superSize ) ;
853+ c . _onComplete = onComplete ;
854+ }
855+
856+ private System . Collections . IEnumerator Start ( )
857+ {
858+ yield return new WaitForEndOfFrame ( ) ;
859+ Texture2D tex = null ;
860+ try { tex = ScreenshotUtility . InvokeCaptureScreenshotAsTexture ( _superSize ) ; }
861+ catch ( Exception ex ) { Debug . LogError ( $ "[MCP for Unity] CaptureScreenshotAsTexture failed: { ex . Message } ") ; }
862+ _onComplete ? . Invoke ( tex ) ;
863+ Destroy ( gameObject ) ;
864+ }
865+ }
790866}
0 commit comments