Skip to content

fix: Input simulation overlays stay usable without shipping runtime DLLs#1285

Merged
hatayama merged 6 commits into
mainfrom
feature/hatayama/fix-simulate-bug
Jun 4, 2026
Merged

fix: Input simulation overlays stay usable without shipping runtime DLLs#1285
hatayama merged 6 commits into
mainfrom
feature/hatayama/fix-simulate-bug

Conversation

@hatayama

@hatayama hatayama commented Jun 4, 2026

Copy link
Copy Markdown
Owner

Summary

  • Input simulation overlays remain usable in the Editor without missing prefab components.
  • Player builds no longer include the prefab-only uLoop runtime DLL when the overlay objects are excluded from the build.

User Impact

  • Mouse, keyboard, and input replay simulation tools can show their overlay UI in Play Mode again after the overlay prefab script resolution regression.
  • Apps built from projects that install the package avoid carrying the small prefab-only runtime assembly in Player builds.

Changes

  • Keep the overlay runtime asmdef player-compatible for Editor prefab script resolution while disabling automatic references.
  • Mark the shared overlay prefab hierarchy as EditorOnly and add build-time filtering for the prefab-only runtime DLL.
  • Stabilize replay/mouse simulation coverage so overlay UI and mouse replay behavior are verified consistently.

Verification

  • uloop compile --wait-for-domain-reload true
  • uloop run-tests --test-mode EditMode --filter-type regex --filter-value io.github.hatayama.uLoopMCP.InputVisualizationCanvasPrefabTests
  • uloop run-tests --test-mode EditMode --filter-type regex --filter-value io.github.hatayama.uLoopMCP.(RuntimeAssemblyBuildFilterTests|InputVisualizationCanvasPrefabTests)
  • Verified mouse, mouse UI, and keyboard simulation overlays in the validation project.
  • Built the validation project with Mono and managed stripping disabled; the build succeeded and uLoopMCP.Runtime.dll was absent from the Player managed assemblies.

Overview

This PR fixes a regression where input simulation overlay prefab script references were not resolving in the Editor and prevents the prefab-only runtime DLL from being included in Player builds when overlay objects are excluded. Overlays show UI again in Editor Play Mode while Player builds no longer include the small prefab-only runtime assembly when overlays are excluded.

Changes Summary

  • Make the overlay runtime asmdef player-compatible so Editor prefab script resolution works, but disable auto-references to avoid forcing inclusion in Player builds.
  • Mark the shared input visualization prefab hierarchy as EditorOnly and add build-time filtering to exclude the prefab-only runtime assembly (uLoopMCP.Runtime.dll) from Player managed assemblies.
  • Wrap overlay runtime types in editor-only compilation guards (#if UNITY_EDITOR) to exclude overlay classes from non-editor compilation:
    • Packages/src/Runtime/Common/InputVisualizationCanvas.cs
    • Packages/src/Runtime/RecordInput/RecordInputOverlayPresenter.cs
    • Packages/src/Runtime/RecordInput/RecordInputOverlayView.cs
    • Packages/src/Runtime/ReplayInput/ReplayInputOverlay.cs
    • Packages/src/Runtime/SimulateKeyboard/SimulateKeyboardOverlay.cs
    • Packages/src/Runtime/SimulateMouseInput/SimulateMouseInputOverlay.cs
    • Packages/src/Runtime/SimulateMouseUi/SimulateMouseUiOverlay.cs
  • Add a build-time filter:
    • Packages/src/Editor/Build/RuntimeAssemblyBuildFilter.cs implements IFilterBuildAssemblies and removes uLoopMCP.Runtime.dll from Player builds (skips filtering when BuildOptions.IncludeTestAssemblies is set).
    • Packages/src/Editor/Shared/Config/McpConstants.cs: new constant RUNTIME_ASSEMBLY_FILE_NAME = "uLoopMCP.Runtime.dll".
  • Stabilize replay and mouse simulation coverage and adjust replay timing so the InputSystem UI input module can consume terminal releases without producing spurious frames:
    • Packages/src/Editor/Api/McpTools/ReplayInput/InputReplayer.cs: refactor to manage overlay lifecycle (EnsureOverlayForReplay, ClearOverlayState), gate overlay updates on _showOverlay, separate UI dispatch modes, add ClearPointerState and replay completion/delay handling.
    • Packages/src/Editor/Api/McpTools/ReplayInput/ReplayInputTool.cs: simplify start logic to rely on InputReplayer for overlay setup.

Tests & Verification

  • EditMode tests:
    • Assets/Tests/Editor/InputVisualizationCanvasPrefabTests.cs: validates runtime asmdef includePlatforms/autoReferenced contract, instantiates InputVisualizationCanvas.prefab and asserts overlay component references (keyboard, mouse UI, mouse input, record presenter, replay), and checks SimulateMouseInputOverlay.prefab does not reference a demo/test GUID.
    • Assets/Tests/Editor/RuntimeAssemblyBuildFilterTests.cs: verifies RuntimeAssemblyBuildFilter removes only uLoopMCP.Runtime.dll for normal builds and preserves it when test assemblies are included.
  • PlayMode / E2E:
    • Assets/Tests/PlayMode/SimulateMouseDemoE2ETests.cs: enforces Full HD Game View resolution for reproducible replay tests and shows overlay during replay.
    • Assets/Tests/PlayMode/InputReplayerCompletionTests.cs: validates replay completion behavior relative to Unity UI consumption of terminal releases (firing after UI consumes release, looped replay not inserting empty frames, and matching pointer-up dispatch).
  • Manual validation:
    • Mouse/mouse UI/keyboard overlays validated in the Editor.
    • Player build (Mono, managed stripping disabled) verified uLoopMCP.Runtime.dll absent from managed assemblies when overlays are excluded.

Architecture

classDiagram
    class RuntimeAssemblyBuildFilter {
        -callbackOrder: int
        +OnFilterAssemblies(BuildOptions, string[]) string[]
        -IsRuntimeAssembly(string) bool
    }
    
    class InputReplayer {
        -_showOverlay: bool
        +EnsureOverlayForReplay()
        +ClearOverlayState()
        -ClearPointerState()
        `#ApplyUiEvents`()
    }
    
    class McpConstants {
        +RUNTIME_ASSEMBLY_FILE_NAME: string
    }
    
    RuntimeAssemblyBuildFilter --|> IFilterBuildAssemblies
    RuntimeAssemblyBuildFilter --> McpConstants
    InputReplayer -.-> ReplayInputOverlay
Loading

User Impact

  • Editor Play Mode: Mouse, keyboard, and input replay overlays display UI correctly again.
  • Player Builds: Projects that install the package no longer include the prefab-only uLoopMCP.Runtime.dll when overlays are excluded, reducing build footprint.
  • Tests: New EditMode and PlayMode tests cover prefab contracts, build filtering, and replay completion behavior.

Commit Notes

  • Timing fix for replay completion: delay non-loop replay completion so InputSystemUIInputModule can consume terminal release without producing spurious frames; preserve loop cadence and pointer dispatch mode.
  • Keep runtime assembly in player test builds so PlayMode test players can resolve package test references.

hatayama added 4 commits June 4, 2026 22:40
Keep the runtime assembly attachable without implicit auto-references so package prefabs can resolve their overlay components in consumer projects.

Also remove the demo-only mouse overlay tester from the package prefab and add prefab contract tests to catch editor-only asmdef regressions and package-only missing script references.
Ensure the mouse replay E2E runs against the same Full HD Game View size as its fixture and enables replay visualization so the pointer overlay is exercised.

Wire the overlay prefab references through Unity serialization, and avoid duplicate UI dispatch when InputSystemUIInputModule already consumes injected mouse state.
Tag every GameObject in the shared input visualization prefab as EditorOnly so Unity can exclude the instantiated overlay hierarchy from player scenes while keeping prefab script references resolvable in the editor.
Keep the runtime asmdef player-compatible so overlay prefabs resolve in the Editor, then remove uLoopMCP.Runtime.dll from Player build assembly lists through Unity's build assembly filter callback.
@coderabbitai

coderabbitai Bot commented Jun 4, 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: eee6c725-0b73-41b5-950c-d23a9b035fa6

📥 Commits

Reviewing files that changed from the base of the PR and between 16699fc and 48cf40d.

⛔ Files ignored due to path filters (1)
  • Packages/src/TypeScriptServer~/package-lock.json is excluded by !**/package-lock.json and included by **/*.json
📒 Files selected for processing (1)
  • Packages/src/TypeScriptServer~/package.json
✅ Files skipped from review due to trivial changes (1)
  • Packages/src/TypeScriptServer~/package.json

📝 Walkthrough

Walkthrough

Wraps runtime overlay and visualization types in editor-only guards, adds a build-time filter to remove the runtime DLL from player builds, introduces prefab import validation tests, refactors InputReplayer to own overlay lifecycle and UI dispatch behavior, removes overlay init from ReplayInputTool, and stabilizes E2E Game View resolution.

Changes

Editor-only input visualization and replay control

Layer / File(s) Summary
Editor-only compilation guards for overlay and canvas types
Packages/src/Runtime/Common/InputVisualizationCanvas.cs, Packages/src/Runtime/RecordInput/RecordInputOverlayPresenter.cs, Packages/src/Runtime/RecordInput/RecordInputOverlayView.cs, Packages/src/Runtime/ReplayInput/ReplayInputOverlay.cs, Packages/src/Runtime/SimulateKeyboard/SimulateKeyboardOverlay.cs, Packages/src/Runtime/SimulateMouseInput/SimulateMouseInputOverlay.cs, Packages/src/Runtime/SimulateMouseUi/SimulateMouseUiOverlay.cs
Wraps overlay and canvas types with #if UNITY_EDITOR / #endif so they are excluded from non-editor builds.
Build-time runtime assembly filtering
Packages/src/Editor/Shared/Config/McpConstants.cs, Packages/src/Editor/Build/RuntimeAssemblyBuildFilter.cs, Assets/Tests/Editor/RuntimeAssemblyBuildFilterTests.cs
Adds RUNTIME_ASSEMBLY_FILE_NAME, implements RuntimeAssemblyBuildFilter : IFilterBuildAssemblies to remove uLoopMCP.Runtime.dll from non-test player builds, and adds tests validating behavior.
Prefab structure and component reference validation
Assets/Tests/Editor/InputVisualizationCanvasPrefabTests.cs
New EditMode tests validate the runtime .asmdef values, instantiate InputVisualizationCanvas.prefab to assert expected overlay component references, and ensure SimulateMouseInputOverlay.prefab does not reference a demo tester GUID; includes helpers to read files and extract .meta GUIDs.
Input replay overlay state and UI dispatch refactoring
Packages/src/Editor/Api/McpTools/ReplayInput/InputReplayer.cs, Packages/src/Editor/Api/McpTools/ReplayInput/ReplayInputTool.cs
Centralizes overlay lifecycle and state clearing in InputReplayer, gates overlay visuals on _showOverlay, computes and caches manual UI dispatch mode, splits manual vs non-manual pointer handling, introduces ClearPointerState(), updates completion handling, and removes overlay initialization from ReplayInputTool.
PlayMode and E2E test updates with Game View resolution control
Assets/Tests/PlayMode/InputReplayerCompletionTests.cs, Assets/Tests/PlayMode/SimulateMouseDemoE2ETests.cs
Adds PlayMode tests for replay completion/loop behavior, enforces Full HD Game View resolution in E2E tests via editor reflection helpers, and enables the replay overlay for visual validation.
NPM override bump
Packages/src/TypeScriptServer~/package.json
Updates hono override from 4.12.18 to 4.12.23.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main focus of the PR: ensuring input simulation overlays remain functional without including a prefab-only runtime DLL in Player builds.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/hatayama/fix-simulate-bug

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.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 22 files

Re-trigger cubic

hatayama added 2 commits June 5, 2026 01:54
Delay non-loop replay completion until InputSystemUIInputModule can consume the terminal release, keep loop cadence gapless, and preserve pointer dispatch mode across press/release. Keep the runtime assembly in player test builds so PlayMode test players can resolve package test references.
Bump the TypeScript server Hono override past the vulnerable <=4.12.20 range so the NPM supply chain security audit passes.

@coderabbitai coderabbitai Bot 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Packages/src/Editor/Api/McpTools/ReplayInput/InputReplayer.cs (1)

155-163: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clamp replay progress during the delayed-completion frame.

On Line 161, the method returns after _currentFrame has already advanced past TotalFrames. That leaves IsReplaying == true for one frame while CurrentFrame/Progress expose an unrecorded extra frame, which can leak a > 1.0 progress value to any observer.

Suggested fix
             if (_eventIndex >= _data.Frames.Count && _currentFrame > _data.Metadata.TotalFrames)
             {
                 if (_delayCompletionForUiModule)
                 {
                     _delayCompletionForUiModule = false;
+                    _currentFrame = _data.Metadata.TotalFrames;
                     return;
                 }
 
                 if (_loop)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Packages/src/Editor/Api/McpTools/ReplayInput/InputReplayer.cs` around lines
155 - 163, When delaying completion in InputReplayer (check
_delayCompletionForUiModule inside the block where _currentFrame was just
incremented and _eventIndex >= _data.Frames.Count), clamp the exposed replay
position so observers don't see a frame > TotalFrames: before returning, set
_currentFrame (or the value used by CurrentFrame/Progress) to
Math.Min(_currentFrame, _data.Metadata.TotalFrames) (or decrement _currentFrame
back to _data.Metadata.TotalFrames) so IsReplaying can remain true for the extra
UI frame without letting CurrentFrame/Progress exceed TotalFrames; update the
branch that returns when _delayCompletionForUiModule is true to perform this
clamp.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@Packages/src/Editor/Api/McpTools/ReplayInput/InputReplayer.cs`:
- Around line 155-163: When delaying completion in InputReplayer (check
_delayCompletionForUiModule inside the block where _currentFrame was just
incremented and _eventIndex >= _data.Frames.Count), clamp the exposed replay
position so observers don't see a frame > TotalFrames: before returning, set
_currentFrame (or the value used by CurrentFrame/Progress) to
Math.Min(_currentFrame, _data.Metadata.TotalFrames) (or decrement _currentFrame
back to _data.Metadata.TotalFrames) so IsReplaying can remain true for the extra
UI frame without letting CurrentFrame/Progress exceed TotalFrames; update the
branch that returns when _delayCompletionForUiModule is true to perform this
clamp.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3e31ba8c-ba5e-4d3c-8d4f-7ad0760f9269

📥 Commits

Reviewing files that changed from the base of the PR and between 1a2e3c9 and 16699fc.

⛔ Files ignored due to path filters (1)
  • Assets/Tests/PlayMode/InputReplayerCompletionTests.cs.meta is excluded by none and included by none
📒 Files selected for processing (5)
  • Assets/Tests/Editor/RuntimeAssemblyBuildFilterTests.cs
  • Assets/Tests/PlayMode/InputReplayerCompletionTests.cs
  • Assets/Tests/PlayMode/SimulateMouseDemoE2ETests.cs
  • Packages/src/Editor/Api/McpTools/ReplayInput/InputReplayer.cs
  • Packages/src/Editor/Build/RuntimeAssemblyBuildFilter.cs
🚧 Files skipped from review as they are similar to previous changes (2)
  • Assets/Tests/Editor/RuntimeAssemblyBuildFilterTests.cs
  • Packages/src/Editor/Build/RuntimeAssemblyBuildFilter.cs

@hatayama
hatayama merged commit e271514 into main Jun 4, 2026
9 checks passed
@hatayama
hatayama deleted the feature/hatayama/fix-simulate-bug branch June 4, 2026 23:41
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.

1 participant