Skip to content

Conversation

@Hashibutogarasu
Copy link
Contributor

@Hashibutogarasu Hashibutogarasu commented Nov 29, 2025

This pull request updates the logic for showing the setup window in the Unity Editor to ensure it only appears once per editor session, even across domain reloads. The main improvement is switching from a static boolean flag to Unity's SessionState, which persists across assembly reloads and playmode transitions. Additionally, logging statements have been refactored for clarity and consistency.

Setup window session management:

  • Replaced the static _hasCheckedThisSession flag with a persistent SessionState key (SessionCheckedKey) to track if the setup check has already run in the current editor session. This prevents the setup window from reappearing after script recompiles or playmode toggles.
  • Updated the logic in CheckSetupNeeded() to use SessionState.GetBool and SessionState.SetBool for session tracking, ensuring the check only runs once per session.

Logging improvements:

  • Refactored logging statements to use multi-line formatting for better readability and maintainability. This affects messages for skipping the setup window due to remote defaults and when the setup has already been completed or dismissed.

Minor cleanup:

  • Removed an unnecessary blank line at the end of the file for consistency.

Summary by CodeRabbit

  • Improvements

    • Setup window now persists its "checked this session" state across domain reloads and play/edit transitions, so setup prompts run only once per editor session.
    • More reliable health-check behavior and safer null handling to reduce spurious errors during editor workflows.
    • Improved logging and message readability when skipping setup or reporting errors.
  • New Features

    • Bulk window management: the MCP window toggle can detect and close or show all open MCP windows.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 29, 2025

Walkthrough

Replaces a per-session static flag with SessionState persistence for setup-window gating, adds public helpers to query/close MCP editor windows (HasAnyOpenWindow, CloseAllOpenWindows), updates the menu toggle to use those helpers, and tightens null-safety and logging around window/health-check logic. No public signature removals.

Changes

Cohort / File(s) Change Summary
Setup window session persistence
MCPForUnity/Editor/Setup/SetupWindowService.cs
Replace private static per-session flag with a SessionCheckedKey constant and use SessionState.GetBool/SetBool to ensure CheckSetupNeeded runs at most once per Editor session (survives domain reloads/play-mode transitions). Gate logic now skips when remote defaults indicate no setup or when the session key is set. Reformat logging calls; no exported signature changes.
Editor window helpers & safety fixes
MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs
Add public static bool HasAnyOpenWindow() and public static void CloseAllOpenWindows() to query and close all open MCPForUnityEditorWindow instances; CloseAllOpenWindows iterates a copied list and catches per-window exceptions with warnings. Add guiCreated re-entrancy guard in CreateGUI(), reset on disable, update UXML load error formatting, use multi-line lambda bodies for event wiring, and tighten null-safety in ScheduleHealthCheck (guard against null connectionSection and call VerifyBridgeConnectionAsync only when non-null).
Menu toggle integration
MCPForUnity/Editor/MenuItems/MCPForUnityMenu.cs
Replace EditorWindow.HasOpenInstances<T>() + manual iteration/closing with MCPForUnityEditorWindow.HasAnyOpenWindow() and MCPForUnityEditorWindow.CloseAllOpenWindows(). Preserve ShowWindow behavior. Removed some XML comments/regions and adjusted internal logic only.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to:
    • Correctness and uniqueness of the SessionCheckedKey name and its lifetime semantics.
    • Proper iteration and exception handling in CloseAllOpenWindows() to avoid leaking window state.
    • guiCreated re-entrancy guard correctness across domain reloads and disable/enable cycles.
    • ScheduleHealthCheck null-safety changes to ensure intended checks are not silently skipped.

Possibly related PRs

Poem

🐰 I hopped through editor nights and days,

Swapped a static flag for SessionState's ways,
I learned when windows open, learned when to close,
Tucked checks to one session, neat as my nose.
A tiny rabbit dances — tidy code it sows.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title mentions 'EditorPrefs' but the actual changes implement 'SessionState', not EditorPrefs. The title does not accurately reflect the main technical change in the pull request. Update the title to 'fix: Changed flag management to SessionState' to accurately reflect that SessionState (not EditorPrefs) is used for persisting the setup window check across editor sessions.
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f6c6a3a and f8bc576.

📒 Files selected for processing (1)
  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs (8 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs

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 and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
MCPForUnity/Editor/Setup/SetupWindowService.cs (3)

57-61: Good readability improvement.

The multi-line formatting makes the complex conditional easier to parse. Each boolean sub-expression is now clearly visible on its own line.


63-66: Consistent log formatting.

The multi-line format improves readability for the lengthy log message and aligns with the formatting applied to the other log call later in the method.


80-83: Consistent log formatting.

This maintains the same multi-line format applied to the earlier log call, keeping the code style consistent throughout the method.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2126745 and 96f4ce3.

📒 Files selected for processing (1)
  • MCPForUnity/Editor/Setup/SetupWindowService.cs (4 hunks)
🔇 Additional comments (2)
MCPForUnity/Editor/Setup/SetupWindowService.cs (2)

21-25: LGTM! Clear documentation of SessionState usage.

The constant naming and inline comments clearly explain why SessionState is used over a static field. This documentation will help future maintainers understand the persistence behavior across domain reloads.


42-47: Based on my web search verification, I can now provide the rewritten review comment. The technical claims in the original review have been confirmed:

SessionState API verification complete — implementation is correct.

SessionState (UnityEditor.SessionState) is the appropriate API for this use case. It survives domain reloads and Play Mode transitions within the same Editor session, making it ideal for "run once per session" logic. The implementation correctly:

  1. Checks if already executed via SessionState.GetBool with a safe default of false
  2. Returns early on subsequent checks
  3. Marks as executed via SessionState.SetBool before running setup logic
  4. Prevents repeated checks even if early returns occur from exceptions or conditional logic

The pattern matches Unity's recommended approach for Editor session-scoped state. No issues found.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs (2)

30-55: Open-window helpers look solid; consider unified logging

The static OpenWindows set with HasAnyOpenWindow/CloseAllOpenWindows is a clean way to coordinate with external callers, and copying to an array before closing avoids collection-modification issues.

For consistency with the rest of the plugin’s logging (and to keep the MCP prefix), consider routing the warning through McpLog instead of Debug.LogWarning:

-                catch (Exception ex)
-                {
-                    Debug.LogWarning($"Error closing MCP window: {ex.Message}");
-                }
+                catch (Exception ex)
+                {
+                    McpLog.Warn($"Error closing MCP window: {ex.Message}");
+                }

Optionally, if RequestHealthVerification ever grows logic that might close windows, you may want to mirror the “copy to array” pattern there as well.


111-115: Cross-section event wiring is safe; watch for repeated CreateGUI calls

The new callbacks from McpSettingsSection and McpConnectionSection into clientConfigSection/connectionSection are wired safely with null-conditional access, so missing sections won’t throw.

One thing to be aware of: if Unity ever calls CreateGUI() more than once on the same window instance (e.g., under certain domain reload patterns), these += subscriptions could accumulate. If that’s a concern for your target Unity versions, you could either unsubscribe in OnDisable or guard CreateGUI so wiring happens only once per window.

Also applies to: 126-127

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9aea8e7 and f6c6a3a.

📒 Files selected for processing (1)
  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs (6 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-03T16:00:55.839Z
Learnt from: dsarno
Repo: CoplayDev/unity-mcp PR: 0
File: :0-0
Timestamp: 2025-09-03T16:00:55.839Z
Learning: ComponentResolver in UnityMcpBridge/Editor/Tools/ManageGameObject.cs is a nested static class within ManageGameObject, not a sibling type. The `using static MCPForUnity.Editor.Tools.ManageGameObject;` import is required to access ComponentResolver methods directly without the outer class qualifier.

Applied to files:

  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs
📚 Learning: 2025-10-13T13:27:23.040Z
Learnt from: msanatan
Repo: CoplayDev/unity-mcp PR: 316
File: TestProjects/UnityMCPTests/Assets/Tests/EditMode/Resources.meta:1-8
Timestamp: 2025-10-13T13:27:23.040Z
Learning: UnityMcpBridge is a legacy project kept for backwards compatibility; MCPForUnity is the only active Unity plugin project. GUID collisions between UnityMcpBridge and MCPForUnity are acceptable.

Applied to files:

  • MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs
🧬 Code graph analysis (1)
MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs (2)
MCPForUnity/Editor/Helpers/McpLog.cs (3)
  • Debug (31-35)
  • McpLog (7-52)
  • Error (48-51)
MCPForUnity/Editor/Windows/Components/ClientConfig/McpClientConfigSection.cs (1)
  • UpdateManualConfiguration (155-178)
🔇 Additional comments (3)
MCPForUnity/Editor/Windows/MCPForUnityEditorWindow.cs (3)

7-11: Namespace imports match usages

The added using directives line up with the types used in this file (sections, Editor APIs, UI Toolkit) and keep the class self-contained; no issues here.


68-70: UXML load error logging is clear and consistent

Reformatting the McpLog.Error call into a multi-line statement with the full path interpolated improves readability and keeps error reporting consistent with the rest of the editor tooling.


199-204: Improved null-safety in scheduled health checks

The guard clause if (this == null || connectionSection == null) { return; } correctly prevents a NullReferenceException. In C#, awaiting a null Task always throws NullReferenceException at runtime, so the null-check before await connectionSection.VerifyBridgeConnectionAsync(); is essential. This handles both the destroyed-window case (this == null) and the uninitialized connection section case (connectionSection == null), making the delayed health check safe.

If you later introduce code that can swap out connectionSection, snapshotting it into a local before the null-check would provide extra safety, but this fix is solid as-is.

@dsarno
Copy link
Collaborator

dsarno commented Dec 2, 2025

@Hashibutogarasu Thanks for your contribution, this looks good and is a nice little cleanup and ux improvement. Merging now.

One small note: your title says “Changed flag management to EditorPrefs” but the final implementation uses SessionState (which is a good way to do it)

@dsarno dsarno merged commit b57a2ec into CoplayDev:main Dec 2, 2025
1 check passed
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.

2 participants