Skip to content

Commit c56337e

Browse files
committed
refactor: drop defensive scaffolding made obsolete by module dep declarations (#1122)
Since #1122 declared the Physics 2D, Screen Capture, Image Conversion, etc. built-in modules as required deps in package.json, Unity Package Manager now keeps them enabled while MCP for Unity is installed. Two defensive layers that protected against the now-impossible "module disabled" case become dead code, plus one sub-floor preprocessor gate that was always-true on our declared `unity: 2021.3` floor. Tier 1A — UnityPhysicsCompat.cs - Revert `Type.GetType("UnityEngine.Physics2D, UnityEngine.Physics2DModule")` to `typeof(Physics2D)`. The property-level reflection (for `autoSyncTransforms` deprecation in Unity 6.x) stays — that's a different concern. Tier 1B — TrailControl.cs - Strip `#if UNITY_2021_1_OR_NEWER` gate. Package floor is 2021.3 per package.json, so the `#else` branch ("AddPosition requires Unity 2021.1+") is unreachable. Tier 2 — ScreenshotUtility.cs + callers - Remove `IsScreenCaptureModuleAvailable` property, `ScreenCaptureModuleNotAvailableError` constant, `InvokeCaptureScreenshotAsTexture` helper, and the `s_captureScreenshotMethod` / `s_captureScreenshotAsTextureMethod` / `s_screenCaptureModuleAvailable` reflection caches. - Replace reflective `MethodInfo.Invoke` calls with direct `ScreenCapture.X` calls in `CaptureToProjectFolder`, `CaptureComposited`, and the `ScreenshotCapturer` MonoBehaviour. - Camera-based fallback path (`FindAvailableCamera` + `CaptureFromCameraToProjectFolder`) is preserved — it still handles transient null returns from `ScreenCapture` inside `CaptureComposited`. - Drop pre-flight `if (!IsScreenCaptureModuleAvailable)` gates in `ManageUI.cs` (UI render) and `ManageScene.cs` (screenshot path). - `ProjectInfo` resource: `screenCapture` field is now an invariant `true` (preserves API shape for `mcpforunity://project/info` consumers). Net: 144 lines removed, 15 added. No new tests — the changes are pure removal of code paths that cannot fire with the current deps declared. Related: #1160, #1122.
1 parent e3f822b commit c56337e

6 files changed

Lines changed: 15 additions & 144 deletions

File tree

MCPForUnity/Editor/Resources/Project/ProjectInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static object HandleCommand(JObject @params)
3838
textmeshpro = IsPackageInstalled("com.unity.textmeshpro"),
3939
inputsystem = IsPackageInstalled("com.unity.inputsystem"),
4040
uiToolkit = true,
41-
screenCapture = MCPForUnity.Runtime.Helpers.ScreenshotUtility.IsScreenCaptureModuleAvailable,
41+
screenCapture = true,
4242
}
4343
};
4444

MCPForUnity/Editor/Tools/ManageScene.cs

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -678,24 +678,9 @@ private static object CaptureScreenshot(SceneCommand cmd)
678678
return new SuccessResponse(message, BuildScreenshotResponseData(result, targetCamera.name, includeImage));
679679
}
680680

681-
// Default path: use ScreenCapture API if available, camera fallback otherwise
682-
bool screenCaptureAvailable = ScreenshotUtility.IsScreenCaptureModuleAvailable;
681+
// Default path: ScreenCapture API for 2022.1+, camera fallback required on older versions.
682+
#if !UNITY_2022_1_OR_NEWER
683683
bool hasCameraFallback = Camera.main != null || UnityFindObjectsCompat.FindAll<Camera>().Length > 0;
684-
685-
#if UNITY_2022_1_OR_NEWER
686-
if (!screenCaptureAvailable && !hasCameraFallback)
687-
{
688-
return new ErrorResponse(
689-
"Cannot capture screenshot. The Screen Capture module is not enabled and no Camera was found in the scene. " +
690-
"Please either: (1) Enable the Screen Capture module: Window > Package Manager > Built-in > Screen Capture > Enable, " +
691-
"or (2) Add a Camera to your scene for camera-based fallback capture."
692-
);
693-
}
694-
if (!screenCaptureAvailable)
695-
{
696-
McpLog.Warn("[ManageScene] Screen Capture module not enabled. Using camera-based fallback.");
697-
}
698-
#else
699684
if (!hasCameraFallback)
700685
{
701686
return new ErrorResponse(

MCPForUnity/Editor/Tools/ManageUI.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -927,12 +927,6 @@ private static object RenderUI(JObject @params)
927927
}
928928

929929
// ── Case 2: start a new capture ───────────────────────────────────
930-
// Verify the ScreenCapture module is enabled before attempting capture.
931-
if (!ScreenshotUtility.IsScreenCaptureModuleAvailable)
932-
{
933-
return new ErrorResponse(ScreenshotUtility.ScreenCaptureModuleNotAvailableError);
934-
}
935-
936930
// Only one capture in flight at a time. If one is already pending,
937931
// reject rather than silently overwriting the state.
938932
if (s_pendingCaptureStarted)

MCPForUnity/Editor/Tools/Vfx/TrailControl.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,9 @@ public static object Emit(JObject @params)
2424

2525
RendererHelpers.EnsureMaterial(tr);
2626

27-
#if UNITY_2021_1_OR_NEWER
2827
Vector3 pos = ManageVfxCommon.ParseVector3(@params["position"]);
2928
tr.AddPosition(pos);
3029
return new { success = true, message = $"Emitted at ({pos.x}, {pos.y}, {pos.z})" };
31-
#else
32-
return new { success = false, message = "AddPosition requires Unity 2021.1+" };
33-
#endif
3430
}
3531
}
3632
}

MCPForUnity/Runtime/Helpers/ScreenshotUtility.cs

Lines changed: 8 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -50,57 +50,6 @@ public static class ScreenshotUtility
5050
/// or globally via <c>ScreenshotPreferences</c> in the Editor assembly.
5151
/// </summary>
5252
public const string DefaultFolder = "Assets/Screenshots";
53-
private static bool s_loggedLegacyScreenCaptureFallback;
54-
private static bool? s_screenCaptureModuleAvailable;
55-
private static System.Reflection.MethodInfo s_captureScreenshotMethod;
56-
private static System.Reflection.MethodInfo s_captureScreenshotAsTextureMethod;
57-
58-
/// <summary>
59-
/// Checks if the Screen Capture module (com.unity.modules.screencapture) is enabled.
60-
/// This module can be disabled in Package Manager > Built-in, which removes the ScreenCapture class.
61-
/// </summary>
62-
public static bool IsScreenCaptureModuleAvailable
63-
{
64-
get
65-
{
66-
if (!s_screenCaptureModuleAvailable.HasValue)
67-
{
68-
// Check if ScreenCapture type exists (module might be disabled in Package Manager > Built-in)
69-
var screenCaptureType = Type.GetType("UnityEngine.ScreenCapture, UnityEngine.ScreenCaptureModule")
70-
?? Type.GetType("UnityEngine.ScreenCapture, UnityEngine.CoreModule");
71-
s_screenCaptureModuleAvailable = screenCaptureType != null;
72-
if (screenCaptureType != null)
73-
{
74-
s_captureScreenshotMethod = screenCaptureType.GetMethod("CaptureScreenshot",
75-
new Type[] { typeof(string), typeof(int) });
76-
s_captureScreenshotAsTextureMethod = screenCaptureType.GetMethod("CaptureScreenshotAsTexture",
77-
new Type[] { typeof(int) });
78-
}
79-
}
80-
return s_screenCaptureModuleAvailable.Value;
81-
}
82-
}
83-
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-
96-
/// <summary>
97-
/// Error message to display when Screen Capture module is not available.
98-
/// </summary>
99-
public const string ScreenCaptureModuleNotAvailableError =
100-
"The Screen Capture module (com.unity.modules.screencapture) is not enabled. " +
101-
"To use screenshot capture with ScreenCapture API, please enable it in Unity: " +
102-
"Window > Package Manager > Built-in > Screen Capture > Enable. " +
103-
"Alternatively, MCP for Unity will use camera-based capture as a fallback if a Camera exists in the scene.";
10453

10554
private static Camera FindAvailableCamera()
10655
{
@@ -127,44 +76,10 @@ public static ScreenshotCaptureResult CaptureToProjectFolder(
12776
bool ensureUniqueFileName = true,
12877
string folderOverride = null)
12978
{
130-
// Use reflection to call ScreenCapture.CaptureScreenshot so the code compiles
131-
// even when the Screen Capture module (com.unity.modules.screencapture) is disabled.
132-
if (IsScreenCaptureModuleAvailable && s_captureScreenshotMethod != null)
133-
{
134-
ScreenshotCaptureResult result = PrepareCaptureResult(fileName, superSize, ensureUniqueFileName, folderOverride, isAsync: true);
135-
// ScreenCapture.CaptureScreenshot accepts paths relative to the project root.
136-
s_captureScreenshotMethod.Invoke(null, new object[] { result.ProjectRelativePath, result.SuperSize });
137-
return result;
138-
}
139-
else
140-
{
141-
// Module disabled or unavailable - try camera fallback
142-
Debug.LogWarning("[MCP for Unity] " + ScreenCaptureModuleNotAvailableError);
143-
return CaptureWithCameraFallback(fileName, superSize, ensureUniqueFileName, folderOverride);
144-
}
145-
}
146-
147-
private static ScreenshotCaptureResult CaptureWithCameraFallback(string fileName, int superSize, bool ensureUniqueFileName, string folderOverride)
148-
{
149-
if (!s_loggedLegacyScreenCaptureFallback)
150-
{
151-
Debug.Log("[MCP for Unity] Using camera-based screenshot capture. " +
152-
"This requires a Camera in the scene. For best results on Unity 2022.1+, ensure the Screen Capture module is enabled: " +
153-
"Window > Package Manager > Built-in > Screen Capture > Enable.");
154-
s_loggedLegacyScreenCaptureFallback = true;
155-
}
156-
157-
var cam = FindAvailableCamera();
158-
if (cam == null)
159-
{
160-
throw new InvalidOperationException(
161-
"No camera found to capture screenshot. Camera-based capture requires a Camera in the scene. " +
162-
"Either add a Camera to your scene, or enable the Screen Capture module: " +
163-
"Window > Package Manager > Built-in > Screen Capture > Enable."
164-
);
165-
}
166-
167-
return CaptureFromCameraToProjectFolder(cam, fileName, superSize, ensureUniqueFileName, folderOverride: folderOverride);
79+
ScreenshotCaptureResult result = PrepareCaptureResult(fileName, superSize, ensureUniqueFileName, folderOverride, isAsync: true);
80+
// ScreenCapture.CaptureScreenshot accepts paths relative to the project root.
81+
ScreenCapture.CaptureScreenshot(result.ProjectRelativePath, result.SuperSize);
82+
return result;
16883
}
16984

17085
/// <summary>
@@ -283,7 +198,7 @@ private static Texture2D CaptureCompositedAfterFrame(int superSize, int timeoutS
283198
/// <summary>
284199
/// Captures a screenshot using ScreenCapture.CaptureScreenshotAsTexture, which captures the
285200
/// final composited frame including UI Toolkit overlays, post-processing, etc.
286-
/// Falls back to camera-based capture if ScreenCapture is unavailable.
201+
/// Falls back to camera-based capture if ScreenCapture returns null at runtime.
287202
/// </summary>
288203
public static ScreenshotCaptureResult CaptureComposited(
289204
string fileName = null,
@@ -293,16 +208,6 @@ public static ScreenshotCaptureResult CaptureComposited(
293208
int maxResolution = 0,
294209
string folderOverride = null)
295210
{
296-
if (!IsScreenCaptureModuleAvailable || s_captureScreenshotAsTextureMethod == null)
297-
{
298-
var fallbackCamera = FindAvailableCamera();
299-
if (fallbackCamera != null)
300-
return CaptureFromCameraToProjectFolder(fallbackCamera, fileName, superSize, ensureUniqueFileName,
301-
includeImage, maxResolution, folderOverride: folderOverride);
302-
303-
throw new InvalidOperationException("ScreenCapture module is unavailable and no fallback camera found.");
304-
}
305-
306211
ScreenshotCaptureResult result = PrepareCaptureResult(fileName, superSize, ensureUniqueFileName, folderOverride: folderOverride, isAsync: false);
307212
Texture2D tex = null;
308213
Texture2D downscaled = null;
@@ -315,9 +220,9 @@ public static ScreenshotCaptureResult CaptureComposited(
315220
// composited; route through WaitForEndOfFrame instead.
316221
tex = Application.isPlaying
317222
? CaptureCompositedAfterFrame(result.SuperSize)
318-
: InvokeCaptureScreenshotAsTexture(result.SuperSize);
223+
: ScreenCapture.CaptureScreenshotAsTexture(result.SuperSize);
319224
#else
320-
tex = InvokeCaptureScreenshotAsTexture(result.SuperSize);
225+
tex = ScreenCapture.CaptureScreenshotAsTexture(result.SuperSize);
321226
#endif
322227
if (tex == null)
323228
{
@@ -857,7 +762,7 @@ private System.Collections.IEnumerator Start()
857762
{
858763
yield return new WaitForEndOfFrame();
859764
Texture2D tex = null;
860-
try { tex = ScreenshotUtility.InvokeCaptureScreenshotAsTexture(_superSize); }
765+
try { tex = ScreenCapture.CaptureScreenshotAsTexture(_superSize); }
861766
catch (Exception ex) { Debug.LogError($"[MCP for Unity] CaptureScreenshotAsTexture failed: {ex.Message}"); }
862767
_onComplete?.Invoke(tex);
863768
Destroy(gameObject);

MCPForUnity/Runtime/Helpers/UnityPhysicsCompat.cs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,10 @@ namespace MCPForUnity.Runtime.Helpers
1717
///
1818
/// We use reflection rather than direct property access so calls stay clean of
1919
/// CS0618 warnings AND survive eventual removal of the obsolete property without
20-
/// a recompile of this package. Type lookups go through <see cref="Type.GetType(string)"/>
21-
/// so this file compiles even when the Physics 2D built-in module is disabled in
22-
/// the Package Manager.
20+
/// a recompile of this package.
2321
/// </summary>
2422
public static class UnityPhysicsCompat
2523
{
26-
// Assembly-qualified name — resolved at runtime so the file compiles when the
27-
// Physics 2D built-in module is disabled in the Package Manager.
28-
private const string Physics2DTypeName = "UnityEngine.Physics2D, UnityEngine.Physics2DModule";
2924
/// <summary>
3025
/// Cross-version description of the 3D physics simulation mode.
3126
/// On 2022.2+ this maps onto <c>UnityEngine.SimulationMode</c>; on older
@@ -51,13 +46,9 @@ private static PropertyInfo Physics2DAutoSyncProp
5146
if (!_physics2DProbed)
5247
{
5348
_physics2DProbed = true;
54-
var physics2DType = Type.GetType(Physics2DTypeName);
55-
if (physics2DType != null)
56-
{
57-
_physics2DAutoSync = physics2DType.GetProperty(
58-
"autoSyncTransforms",
59-
BindingFlags.Public | BindingFlags.Static);
60-
}
49+
_physics2DAutoSync = typeof(Physics2D).GetProperty(
50+
"autoSyncTransforms",
51+
BindingFlags.Public | BindingFlags.Static);
6152
}
6253
return _physics2DAutoSync;
6354
}

0 commit comments

Comments
 (0)