Skip to content

fix: trust the pipeline flag when a domain reload is deferred (#1276) - #1291

Merged
Scriptwonder merged 1 commit into
CoplayDev:betafrom
Scriptwonder:fix/1276-deferred-reload-compiling
Jul 28, 2026
Merged

fix: trust the pipeline flag when a domain reload is deferred (#1276)#1291
Scriptwonder merged 1 commit into
CoplayDev:betafrom
Scriptwonder:fix/1276-deferred-reload-compiling

Conversation

@Scriptwonder

@Scriptwonder Scriptwonder commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Fixes #1276.

The bug

EditorApplication.isCompiling conflates three distinct states:

  1. actually compiling
  2. compilation queued
  3. compilation finished, but the assembly reload is deferred

A project holding EditorApplication.LockReloadAssemblies sits in state 3 for as long as the lock is held. No compilation is running, but isCompiling stays true the entire time — and any code gated on it refuses work indefinitely.

Eight call sites read the raw flag:

Site Symptom while a reload is held
StdioBridgeHost.IsCompiling bridge never starts — the headline symptom
StdioBridgeReloadHandler resume deferred to delayCall instead of running immediately
TestJobManager (init timeout) timeout mis-attributed to compilation
TestJobManager (blocked reason) reports a bogus "compiling" block
ManageScriptableObject rejects every call
UnityReflect "Cannot reflect while Unity is compiling"
RefreshUnity (wait tick) wait_for_ready never completes
RefreshUnity (resulting state) reports "compiling" when idle

The fix

Route all eight through EditorStateCache.GetActualIsCompiling(), which short-circuits to false when isCompiling is false and otherwise trusts the event-tracked CompilationPipeline flag.

Also drops the isPlaying gate that previously limited this workaround to play mode — the same false positive occurs outside play mode, which is exactly what #1276 reports. The existing #549 (Recompile-After-Finished-Playing) case is unaffected and still covered.

Two dead reflection probes that could never be reached are deleted rather than left in place, per the repo's delete-don't-deprecate policy.

The load-bearing assumption, verified

The fix only works if CompilationPipeline.compilationFinished actually fires while LockReloadAssemblies is held. It does. Reproduced live in the Editor:

LockReloadAssemblies() -> RequestScriptCompilation() -> read state

EditorApplication.isCompiling      = True
_pipelineCompilationRunning        = False
GetActualIsCompiling()             = False   <- fixed
(previous behaviour would return    True)

Then confirmed end-to-end per call site: with a reload held, unity_reflect previously returned "Cannot reflect while Unity is compiling" and now reaches parameter validation ('class_name' parameter is required), and refresh_unity previously reported resulting_state: "compiling" and now reports idle.

An earlier draft of this fix added a separate _pipelineCompilationFinished flag. That turned out to be unnecessary given the above, and would have left the flag set after a failed compile — dropped.

Tests

Full EditMode suite on 2021.3.45f2: 1168 total / 1094 passed / 0 failed / 74 skipped.

Known remaining sites, deliberately not touched

Three display-only reads still use the raw flag and are cosmetic rather than functional: McpConnectionSection.cs:382, McpConnectionSection.cs:640, ManagePackages.cs:603.

The EditMode harness itself is also affected — TestUtilities.cs:65 spins on while (EditorApplication.isCompiling || EditorApplication.isUpdating), so a held reload makes every SetUp burn its 180s timeout. That is a test-infrastructure change and belongs in its own PR rather than riding along here.

Summary by CodeRabbit

  • Bug Fixes
    • Improved detection of Unity’s compilation state across editor operations.
    • Reduced false positives and timing issues during script compilation and assembly reloads.
    • Improved reliability of command retries, readiness checks, test jobs, reflection, and automatic connection recovery while Unity is compiling.

…Dev#1276)

EditorApplication.isCompiling conflates three states: actually compiling,
compilation queued, and finished-but-reload-deferred. A project holding
EditorApplication.LockReloadAssemblies sits in the third state for as long
as the lock is held, with no compilation running, and isCompiling stays
true the whole time.

Eight call sites gated on that raw flag, so they refused work indefinitely:
the stdio bridge would not start, unity_reflect and manage_scriptable_object
returned "Unity is compiling", refresh_unity reported the wrong resulting
state and never completed its wait, the stdio reload handler deferred its
resume, and TestJobManager both mis-attributed its init timeout and reported
a bogus "compiling" block reason.

Route all eight through EditorStateCache.GetActualIsCompiling(), which falls
back to the event-tracked CompilationPipeline flag, and drop the isPlaying
gate that previously limited the workaround to play mode.

Verified live: with LockReloadAssemblies held after RequestScriptCompilation,
EditorApplication.isCompiling is true while the pipeline flag is false, so
CompilationPipeline.compilationFinished does fire while the reload is held.
Copilot AI review requested due to automatic review settings July 28, 2026 16:19
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c2dae6a1-1036-4426-a869-f79f3130ec61

📥 Commits

Reviewing files that changed from the base of the PR and between bd72241 and 777e8a9.

📒 Files selected for processing (7)
  • MCPForUnity/Editor/Services/EditorStateCache.cs
  • MCPForUnity/Editor/Services/StdioBridgeReloadHandler.cs
  • MCPForUnity/Editor/Services/TestJobManager.cs
  • MCPForUnity/Editor/Services/Transport/Transports/StdioBridgeHost.cs
  • MCPForUnity/Editor/Tools/ManageScriptableObject.cs
  • MCPForUnity/Editor/Tools/RefreshUnity.cs
  • MCPForUnity/Editor/Tools/UnityReflect.cs

📝 Walkthrough

Walkthrough

Changes

The PR centralizes Unity compilation detection through EditorStateCache.GetActualIsCompiling(), using the event-tracked pipeline state to avoid deferred domain-reload false positives. Bridge services, test jobs, readiness polling, script management, and reflection gates now use this helper.

Compilation-state gating

Layer / File(s) Summary
Authoritative compilation-state detection
MCPForUnity/Editor/Services/EditorStateCache.cs
GetActualIsCompiling() now returns the event-tracked pipeline state when Unity’s raw compiling flag is set, with updated documentation and comments.
Bridge reload and startup gates
MCPForUnity/Editor/Services/StdioBridgeReloadHandler.cs, MCPForUnity/Editor/Services/Transport/Transports/StdioBridgeHost.cs
Stdio reload and startup checks use EditorStateCache.GetActualIsCompiling() instead of raw or reflection-based checks.
Tool and test readiness gates
MCPForUnity/Editor/Services/TestJobManager.cs, MCPForUnity/Editor/Tools/ManageScriptableObject.cs, MCPForUnity/Editor/Tools/RefreshUnity.cs, MCPForUnity/Editor/Tools/UnityReflect.cs
Job timeout handling, blocked reasons, retries, readiness polling, result state, and reflection gating use the centralized compilation status.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: bug

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main fix: trusting the pipeline flag when deferred domain reload keeps compiling state false-positive.
Description check ✅ Passed The description covers the bug, fix, affected call sites, testing, and related issue, though several template sections are unfilled.
Linked Issues check ✅ Passed The PR implements the #1276 fix by routing the relevant checks through EditorStateCache.GetActualIsCompiling and removing the play-mode-only limitation.
Out of Scope Changes check ✅ Passed The changes stay within the reported compiling-state bug and include only supporting cleanup and documentation updates.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a Unity Editor readiness/“busy: compiling” false-positive that occurs when compilation has finished but the assembly reload is deferred (e.g., via EditorApplication.LockReloadAssemblies). It centralizes “actual compiling” detection in EditorStateCache.GetActualIsCompiling() and routes functional gates through it so tools and the stdio bridge don’t remain blocked indefinitely.

Changes:

  • Updates EditorStateCache.GetActualIsCompiling() to rely on event-tracked CompilationPipeline start/finish state whenever EditorApplication.isCompiling is true (covering both play-mode and deferred-reload scenarios).
  • Replaces direct EditorApplication.isCompiling reads (and dead reflection probes) across key call sites (bridge startup/resume, tools, test-job gating).
  • Aligns readiness reporting in refresh_unity and related wait logic with the new “actual compiling” signal.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
MCPForUnity/Editor/Services/EditorStateCache.cs Broadens GetActualIsCompiling() semantics beyond play mode and documents the deferred-reload cases.
MCPForUnity/Editor/Services/StdioBridgeReloadHandler.cs Uses GetActualIsCompiling() to avoid delaying bridge resume when a domain reload is deferred.
MCPForUnity/Editor/Services/TestJobManager.cs Uses GetActualIsCompiling() to avoid misattributing init timeouts / blocked reasons to “compiling”.
MCPForUnity/Editor/Services/Transport/Transports/StdioBridgeHost.cs Gates stdio bridge startup on GetActualIsCompiling() (removes reflection probe).
MCPForUnity/Editor/Tools/ManageScriptableObject.cs Prevents rejecting calls purely due to deferred-reload isCompiling false positives.
MCPForUnity/Editor/Tools/RefreshUnity.cs Ensures wait_for_ready and resulting_state don’t stick on “compiling” during deferred reload.
MCPForUnity/Editor/Tools/UnityReflect.cs Avoids blocking reflection due to deferred-reload isCompiling false positives.
Comments suppressed due to low confidence (1)

MCPForUnity/Editor/Services/EditorStateCache.cs:557

  • GetActualIsCompiling() now drives multiple functional gates (bridge startup, tool readiness, test job timeouts) but there’s no automated regression test for the #1276 scenario (LockReloadAssemblies held after compilation finished) to ensure this stays fixed across Unity versions. Consider adding an EditMode test that holds LockReloadAssemblies(), triggers a compile (or simulates the post-compile deferred-reload window), and asserts GetActualIsCompiling() becomes false while EditorApplication.isCompiling remains true, then releases the lock in tear-down to avoid contaminating other tests.
        internal static bool GetActualIsCompiling()
        {
            // If EditorApplication.isCompiling is false, Unity is definitely not compiling
            if (!EditorApplication.isCompiling)
            {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Scriptwonder
Scriptwonder merged commit 94f192b into CoplayDev:beta Jul 28, 2026
4 checks passed
@Scriptwonder
Scriptwonder deleted the fix/1276-deferred-reload-compiling branch July 28, 2026 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

All tools stuck on "busy: compiling" when a project defers domain reload via EditorApplication.LockReloadAssemblies

2 participants