diff --git a/MCPForUnity/Editor/Services/EditorStateCache.cs b/MCPForUnity/Editor/Services/EditorStateCache.cs
index 54625c2e4..d02b26528 100644
--- a/MCPForUnity/Editor/Services/EditorStateCache.cs
+++ b/MCPForUnity/Editor/Services/EditorStateCache.cs
@@ -260,8 +260,8 @@ static EditorStateCache()
EditorApplication.playModeStateChanged += _ => ForceUpdate("playmode");
// Tracks whether an assembly compilation is actually running, for
- // GetActualIsCompiling's Play-mode check. Statics reset on domain reload
- // and this [InitializeOnLoad] ctor re-subscribes, so the flag is per-domain.
+ // GetActualIsCompiling. Statics reset on domain reload and this
+ // [InitializeOnLoad] ctor re-subscribes, so the flag is per-domain.
UnityEditor.Compilation.CompilationPipeline.compilationStarted += _ => _pipelineCompilationRunning = true;
UnityEditor.Compilation.CompilationPipeline.compilationFinished += _ => _pipelineCompilationRunning = false;
@@ -288,7 +288,7 @@ private static void OnUpdate()
{
// Throttle to reduce overhead while keeping the snapshot fresh enough for polling clients.
double now = EditorApplication.timeSinceStartup;
- // Use GetActualIsCompiling() to avoid Play mode false positives (issue #582)
+ // Use GetActualIsCompiling() to avoid isCompiling false positives (issues #549, #1276)
bool isCompiling = GetActualIsCompiling();
// Check for compilation edge transitions (always update on these)
@@ -543,10 +543,12 @@ public static JObject GetSnapshot()
private static bool _pipelineCompilationRunning;
///
- /// Returns the actual compilation state, working around a known Unity quirk where
- /// EditorApplication.isCompiling can return false positives in Play mode (e.g. a
- /// recompile deferred by Recompile-After-Finished-Playing keeps it true for the
- /// whole play session). See: https://github.com/CoplayDev/unity-mcp/issues/549
+ /// Returns the actual compilation state, working around known Unity quirks where
+ /// EditorApplication.isCompiling reports false positives while no compilation is
+ /// running: a recompile deferred by Recompile-After-Finished-Playing keeps it true
+ /// for the whole play session (issue #549), and a project holding
+ /// EditorApplication.LockReloadAssemblies keeps it true until the lock is released
+ /// (issue #1276). In both cases the event-tracked pipeline flag is authoritative.
///
internal static bool GetActualIsCompiling()
{
@@ -556,16 +558,9 @@ internal static bool GetActualIsCompiling()
return false;
}
- // In Play mode, trust the event-tracked pipeline state instead: a deferred
- // recompile keeps EditorApplication.isCompiling true without any compilation
- // actually running.
- if (EditorApplication.isPlaying)
- {
- return _pipelineCompilationRunning;
- }
-
- // Outside Play mode the raw signal is reliable.
- return true;
+ // Otherwise trust the event-tracked pipeline state: isCompiling stays true for as
+ // long as an assembly reload is deferred, with no compilation actually running.
+ return _pipelineCompilationRunning;
}
}
}
diff --git a/MCPForUnity/Editor/Services/StdioBridgeReloadHandler.cs b/MCPForUnity/Editor/Services/StdioBridgeReloadHandler.cs
index cfa4d7286..4d9bb1ab1 100644
--- a/MCPForUnity/Editor/Services/StdioBridgeReloadHandler.cs
+++ b/MCPForUnity/Editor/Services/StdioBridgeReloadHandler.cs
@@ -114,14 +114,8 @@ private static void OnAfterAssemblyReload()
}
// If the editor is not compiling, attempt an immediate restart without relying on editor focus.
- bool isCompiling = EditorApplication.isCompiling;
- try
- {
- var pipeline = Type.GetType("UnityEditor.Compilation.CompilationPipeline, UnityEditor");
- var prop = pipeline?.GetProperty("isCompiling", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
- if (prop != null) isCompiling |= (bool)prop.GetValue(null);
- }
- catch { }
+ // Routed through EditorStateCache so a deferred reload (issue #1276) does not block resume.
+ bool isCompiling = EditorStateCache.GetActualIsCompiling();
if (!isCompiling)
{
diff --git a/MCPForUnity/Editor/Services/TestJobManager.cs b/MCPForUnity/Editor/Services/TestJobManager.cs
index d162476e8..bdf626036 100644
--- a/MCPForUnity/Editor/Services/TestJobManager.cs
+++ b/MCPForUnity/Editor/Services/TestJobManager.cs
@@ -502,7 +502,7 @@ internal static TestJob GetJob(string jobId)
{
long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
long initTimeout = job.InitTimeoutMs > 0 ? job.InitTimeoutMs : DefaultInitializationTimeoutMs;
- if (!EditorApplication.isCompiling && !EditorApplication.isUpdating && now - job.StartedUnixMs > initTimeout)
+ if (!EditorStateCache.GetActualIsCompiling() && !EditorApplication.isUpdating && now - job.StartedUnixMs > initTimeout)
{
McpLog.Warn($"[TestJobManager] Job {jobId} failed to initialize within {initTimeout}ms, auto-failing");
job.Status = TestJobStatus.Failed;
@@ -589,7 +589,7 @@ private static string GetBlockedReason(TestJob job)
return "editor_unfocused";
}
- if (EditorApplication.isCompiling)
+ if (EditorStateCache.GetActualIsCompiling())
{
return "compiling";
}
diff --git a/MCPForUnity/Editor/Services/Transport/Transports/StdioBridgeHost.cs b/MCPForUnity/Editor/Services/Transport/Transports/StdioBridgeHost.cs
index c4fb2438d..a6a0559d0 100644
--- a/MCPForUnity/Editor/Services/Transport/Transports/StdioBridgeHost.cs
+++ b/MCPForUnity/Editor/Services/Transport/Transports/StdioBridgeHost.cs
@@ -237,24 +237,10 @@ private static void EnsureStartedOnEditorIdle()
}
}
- private static bool IsCompiling()
- {
- if (EditorApplication.isCompiling)
- {
- return true;
- }
- try
- {
- Type pipeline = Type.GetType("UnityEditor.Compilation.CompilationPipeline, UnityEditor");
- var prop = pipeline?.GetProperty("isCompiling", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
- if (prop != null)
- {
- return (bool)prop.GetValue(null);
- }
- }
- catch { }
- return false;
- }
+ // Routed through EditorStateCache so a deferred domain reload (issue #1276) does not
+ // pin the bridge off: raw EditorApplication.isCompiling stays true for as long as the
+ // reload is held, and this gates bridge startup.
+ private static bool IsCompiling() => EditorStateCache.GetActualIsCompiling();
public static void Start()
{
diff --git a/MCPForUnity/Editor/Tools/ManageScriptableObject.cs b/MCPForUnity/Editor/Tools/ManageScriptableObject.cs
index c508e9fc2..2ddd021c3 100644
--- a/MCPForUnity/Editor/Tools/ManageScriptableObject.cs
+++ b/MCPForUnity/Editor/Tools/ManageScriptableObject.cs
@@ -4,6 +4,7 @@
using System.Linq;
using System.Text.RegularExpressions;
using MCPForUnity.Editor.Helpers;
+using MCPForUnity.Editor.Services;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEngine;
@@ -44,7 +45,7 @@ public static object HandleCommand(JObject @params)
return new ErrorResponse(CodeInvalidParams);
}
- if (EditorApplication.isCompiling || EditorApplication.isUpdating)
+ if (EditorStateCache.GetActualIsCompiling() || EditorApplication.isUpdating)
{
// Unity is transient; treat as retryable on the client side.
return new ErrorResponse(CodeCompilingOrReloading, new { hint = "retry" });
diff --git a/MCPForUnity/Editor/Tools/RefreshUnity.cs b/MCPForUnity/Editor/Tools/RefreshUnity.cs
index 537472ac0..a7736aa7e 100644
--- a/MCPForUnity/Editor/Tools/RefreshUnity.cs
+++ b/MCPForUnity/Editor/Tools/RefreshUnity.cs
@@ -109,7 +109,7 @@ await WaitForUnityReadyAsync(
}
}
- string resultingState = EditorApplication.isCompiling
+ string resultingState = EditorStateCache.GetActualIsCompiling()
? "compiling"
: (EditorApplication.isUpdating ? "asset_import" : "idle");
@@ -146,7 +146,7 @@ void Tick()
return;
}
- if (!EditorApplication.isCompiling
+ if (!EditorStateCache.GetActualIsCompiling()
&& !EditorApplication.isUpdating
&& !TestRunStatus.IsRunning
&& !EditorApplication.isPlayingOrWillChangePlaymode)
diff --git a/MCPForUnity/Editor/Tools/UnityReflect.cs b/MCPForUnity/Editor/Tools/UnityReflect.cs
index 06aee0d7f..236b74342 100644
--- a/MCPForUnity/Editor/Tools/UnityReflect.cs
+++ b/MCPForUnity/Editor/Tools/UnityReflect.cs
@@ -6,6 +6,7 @@
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using MCPForUnity.Editor.Helpers;
+using MCPForUnity.Editor.Services;
using MCPForUnity.Runtime.Helpers;
using Newtonsoft.Json.Linq;
using UnityEditor;
@@ -99,7 +100,7 @@ private static Dictionary GetAssemblyTypeCache()
public static object HandleCommand(JObject @params)
{
- if (EditorApplication.isCompiling)
+ if (EditorStateCache.GetActualIsCompiling())
return new ErrorResponse("Cannot reflect while Unity is compiling. Wait for domain reload to complete.");
if (@params == null)