Skip to content

feat: Add a raycast tool for checking what a Game View coordinate hits in 3D physics#1659

Merged
hatayama merged 2 commits into
v3-betafrom
feat/port-stream-c1-raycast-tool
Jul 9, 2026
Merged

feat: Add a raycast tool for checking what a Game View coordinate hits in 3D physics#1659
hatayama merged 2 commits into
v3-betafrom
feat/port-stream-c1-raycast-tool

Conversation

@hatayama

@hatayama hatayama commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a raycast tool: check what a top-left Game View coordinate hits in Unity's 3D physics before driving simulate-mouse-ui.

User Impact

  • Previously there was no way to inspect 3D physics hit results at a specific screenshot/UI coordinate without writing custom dynamic code.
  • Now uloop raycast --x <x> --y <y> reports the hit object, layer, distance, and hit point/normal, using the same top-left Game View coordinate system as simulate-mouse-ui.

Changes

  • New self-contained FirstPartyTools/Raycast/ tool (Tool/Schema/Response, Skill/SKILL.md, own asmdef), following the same self-contained pattern as SimulateMouseUi.
  • New shared Common/GameView/ module (GameViewCoordinateUtility, GameViewRaycastUtility) for the top-left/bottom-left Game View coordinate conversion, shared the same way Common/MouseUi already shares GameObjectPathUtility.
  • Added the missing raycast-related constants to UnityCliLoopConstants.
  • Ported RaycastToolTests/GameViewCoordinateUtilityTests, and hardened RaycastToolTests to disable ambient scene colliders before raycasting so it does not depend on the shared Editor scene being clean.

Verification

  • dist/darwin-arm64/uloop compile — Success, 0 errors/warnings
  • dist/darwin-arm64/uloop run-tests --test-mode EditMode — 1734/1734 passed (+7 pre-existing unrelated skips)
  • dist/darwin-arm64/uloop run-tests --test-mode PlayMode — 92/92 passed

Review in cubic

Ports main's physics raycast query (commit range ending at 90e7483,
#1469-family Raycast feature) onto v3-beta's per-tool asmdef and
[UnityCliLoopTool] auto-discovery architecture. Raycast lets an agent
check what a top-left Game View coordinate hits in 3D physics before
driving simulate-mouse-ui, mirroring the coordinate system already
used by that tool.

- New FirstPartyTools/Raycast/ tool (RaycastTool/Schema/Response,
  Skill/SKILL.md, own asmdef), following SimulateMouseUi's
  self-contained pattern rather than ToolContracts, since Raycast has
  no cross-tool schema sharing yet.
- New Common/GameView/ module (GameViewCoordinateUtility,
  GameViewRaycastUtility) holding the top-left/bottom-left Game View
  coordinate conversion, shared the same way Common/MouseUi already
  shares GameObjectPathUtility.
- Added the missing RAYCAST_DEFAULT_MAX_DISTANCE and
  COORDINATE_SYSTEM_*/COORDINATE_CONVERSION_FORMULA_* constants to
  UnityCliLoopConstants.
- Ported RaycastToolTests and GameViewCoordinateUtilityTests, and
  hardened RaycastToolTests to disable ambient scene colliders before
  raycasting so it does not depend on the shared Editor scene being
  clean.
@coderabbitai

coderabbitai Bot commented Jul 9, 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: 3f4d1a47-1cfc-4c8f-a78f-c8cb764c6a77

📥 Commits

Reviewing files that changed from the base of the PR and between 0c29e4c and 617ca87.

📒 Files selected for processing (1)
  • cli/common/tools/default-tools.json

📝 Walkthrough

Walkthrough

This PR adds a new raycast first-party tool that casts a physics ray from Camera.main using Game View pixel coordinates. It introduces coordinate conversion utilities, raycast utilities, schema/response contracts, editor tests, and skill documentation across three skill directories.

Changes

Raycast Tool

Layer / File(s) Summary
Constants and assembly access
Packages/src/Editor/ToolContracts/UnityCliLoopConstants.cs, Packages/src/Editor/FirstPartyTools/Common/GameView/AssemblyInfo.cs, Packages/src/Editor/FirstPartyTools/Common/MouseUi/AssemblyInfo.cs
Adds raycast constants and InternalsVisibleTo grants exposing internals to the new Raycast editor assembly and test assemblies.
Coordinate conversion utility
Packages/src/Editor/FirstPartyTools/Common/GameView/GameViewCoordinateUtility.cs, Assets/Tests/Editor/GameViewCoordinateUtilityTests.cs
Adds GameViewCoordinateUtility.ConvertInputToUnity to flip top-left input Y into Unity bottom-left Y, plus the GameViewCoordinateConversion struct and tests validating top/center/bottom-right conversions.
Physics raycast utility
Packages/src/Editor/FirstPartyTools/Common/GameView/GameViewRaycastUtility.cs
Adds GameViewRaycastUtility.RaycastFromInputPosition, which converts coordinates, resolves Camera.main, optionally syncs transforms, applies layer/culling masks, runs Physics.RaycastAll, sorts hits by distance, and returns GameViewRaycastResult.
RaycastTool schema, response, execution
Packages/src/Editor/FirstPartyTools/Raycast/RaycastSchema.cs, Packages/src/Editor/FirstPartyTools/Raycast/RaycastResponse.cs, Packages/src/Editor/FirstPartyTools/Raycast/RaycastTool.cs
Defines RaycastSchema parameters, RaycastResponse output fields, and RaycastTool.ExecuteAsync, which validates input, invokes the raycast utility, and maps camera/hit results into the response.
RaycastTool tests
Assets/Tests/Editor/RaycastToolTests.cs
Adds scene setup/teardown and five async tests covering hit, miss, missing camera, hidden culling mask, and disabled autoSyncTransforms scenarios.
Skill documentation
.agents/skills/uloop-raycast/SKILL.md, .claude/skills/uloop-raycast/SKILL.md, Packages/src/Editor/FirstPartyTools/Raycast/Skill/SKILL.md
Adds identical documentation describing tool usage, parameters, coordinate conversion, examples, and JSON output schema across three skill directories.

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

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant RaycastTool
  participant GameViewRaycastUtility
  participant GameViewCoordinateUtility
  participant CameraMain
  participant Physics

  Caller->>RaycastTool: ExecuteAsync(RaycastSchema{X,Y,LayerMask,MaxDistance})
  RaycastTool->>RaycastTool: validate MaxDistance
  RaycastTool->>GameViewRaycastUtility: RaycastFromInputPosition(x, y, layerMask, maxDistance)
  GameViewRaycastUtility->>GameViewCoordinateUtility: ConvertInputToUnity(inputPosition, gameViewSize)
  GameViewCoordinateUtility-->>GameViewRaycastUtility: GameViewCoordinateConversion
  GameViewRaycastUtility->>CameraMain: lookup Camera.main
  alt camera missing
    CameraMain-->>GameViewRaycastUtility: null
    GameViewRaycastUtility-->>RaycastTool: GameViewRaycastResult{CameraFound=false}
    RaycastTool-->>Caller: RaycastResponse{Success=false}
  else camera found
    CameraMain-->>GameViewRaycastUtility: camera
    GameViewRaycastUtility->>Physics: SyncTransforms (optional)
    GameViewRaycastUtility->>Physics: RaycastAll(ray, layerMask & cullingMask)
    Physics-->>GameViewRaycastUtility: RaycastHit[]
    GameViewRaycastUtility-->>RaycastTool: GameViewRaycastResult{sorted hits}
    RaycastTool-->>Caller: RaycastResponse{Hit, HitGameObjectName, Distance, ...}
  end
Loading

Possibly related PRs

  • hatayama/unity-cli-loop#1473: Shares the same top-left Game View → injected Unity coordinate conversion contract and raycast tool/test coverage.
🚥 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 describes the main change: adding a raycast tool for Game View coordinates in 3D physics.
Description check ✅ Passed The description matches the changeset and summarizes the new raycast tool, supporting utilities, tests, and CLI registration.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/port-stream-c1-raycast-tool

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.

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

🧹 Nitpick comments (1)
Assets/Tests/Editor/RaycastToolTests.cs (1)

68-165: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a test for MaxDistance validation.

RaycastTool.ExecuteAsync rejects non-positive, NaN, or infinite MaxDistance values (returning Success = false), but no test in this fixture covers that validation path. Adding a case with an invalid MaxDistance (e.g., 0, -1, or NaN) would protect against regressions in the guard clause.

♻️ Suggested test for MaxDistance validation
         [Test]
         public async Task ExecuteAsync_WhenMaxDistanceIsInvalid_ShouldReturnFailure()
         {
             JObject parameters = new JObject
             {
                 ["x"] = 0f,
                 ["y"] = 0f,
                 ["maxDistance"] = 0f
             };

             RaycastTool tool = new RaycastTool();
             UnityCliLoopToolResponse baseResponse = await tool.ExecuteAsync(parameters, CancellationToken.None);
             RaycastResponse response = (RaycastResponse)baseResponse;

             Assert.That(response.Success, Is.False);
             Assert.That(response.Message, Does.Contain("MaxDistance"));
         }
🤖 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 `@Assets/Tests/Editor/RaycastToolTests.cs` around lines 68 - 165, Add a test in
RaycastToolTests for the MaxDistance guard path in RaycastTool.ExecuteAsync,
since the current fixture only covers hit/miss and camera/culling cases. Use
ExecuteRaycast with an invalid MaxDistance value such as 0, negative, or NaN,
then assert the response returns Success = false and the expected validation
message. Keep the test alongside the existing ExecuteAsync_* cases so the
invalid-distance behavior is covered by this fixture.
🤖 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.

Nitpick comments:
In `@Assets/Tests/Editor/RaycastToolTests.cs`:
- Around line 68-165: Add a test in RaycastToolTests for the MaxDistance guard
path in RaycastTool.ExecuteAsync, since the current fixture only covers hit/miss
and camera/culling cases. Use ExecuteRaycast with an invalid MaxDistance value
such as 0, negative, or NaN, then assert the response returns Success = false
and the expected validation message. Keep the test alongside the existing
ExecuteAsync_* cases so the invalid-distance behavior is covered by this
fixture.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3fe5f60b-b223-4ad0-85ad-b7e725645b4d

📥 Commits

Reviewing files that changed from the base of the PR and between effbd78 and 0c29e4c.

⛔ Files ignored due to path filters (17)
  • Assets/Tests/Editor/GameViewCoordinateUtilityTests.cs.meta is excluded by none and included by none
  • Assets/Tests/Editor/RaycastToolTests.cs.meta is excluded by none and included by none
  • Assets/Tests/Editor/UnityCLILoop.Tests.Editor.asmdef is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Common/GameView.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Common/GameView/AssemblyInfo.cs.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Common/GameView/GameViewCoordinateUtility.cs.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Common/GameView/GameViewRaycastUtility.cs.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Common/GameView/UnityCLILoop.FirstPartyTools.Common.GameView.Editor.asmdef is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Common/GameView/UnityCLILoop.FirstPartyTools.Common.GameView.Editor.asmdef.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Raycast.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Raycast/RaycastResponse.cs.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Raycast/RaycastSchema.cs.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Raycast/RaycastTool.cs.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Raycast/Skill.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Raycast/Skill/SKILL.md.meta is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Raycast/UnityCLILoop.FirstPartyTools.Raycast.Editor.asmdef is excluded by none and included by none
  • Packages/src/Editor/FirstPartyTools/Raycast/UnityCLILoop.FirstPartyTools.Raycast.Editor.asmdef.meta is excluded by none and included by none
📒 Files selected for processing (13)
  • .agents/skills/uloop-raycast/SKILL.md
  • .claude/skills/uloop-raycast/SKILL.md
  • Assets/Tests/Editor/GameViewCoordinateUtilityTests.cs
  • Assets/Tests/Editor/RaycastToolTests.cs
  • Packages/src/Editor/FirstPartyTools/Common/GameView/AssemblyInfo.cs
  • Packages/src/Editor/FirstPartyTools/Common/GameView/GameViewCoordinateUtility.cs
  • Packages/src/Editor/FirstPartyTools/Common/GameView/GameViewRaycastUtility.cs
  • Packages/src/Editor/FirstPartyTools/Common/MouseUi/AssemblyInfo.cs
  • Packages/src/Editor/FirstPartyTools/Raycast/RaycastResponse.cs
  • Packages/src/Editor/FirstPartyTools/Raycast/RaycastSchema.cs
  • Packages/src/Editor/FirstPartyTools/Raycast/RaycastTool.cs
  • Packages/src/Editor/FirstPartyTools/Raycast/Skill/SKILL.md
  • Packages/src/Editor/ToolContracts/UnityCliLoopConstants.cs

Fable 5's review of PR #1659 caught that the new raycast tool had no
entry in cli/common/tools/default-tools.json. The Go CLI's catalog
loader falls back to this embedded catalog when a project has no
.uloop/tools.json cache yet, so a fresh checkout could not resolve
`uloop raycast` even though the Skill/SKILL.md already advertises it.
DefaultToolsCatalogDriftTests only checks embedded-to-live direction,
so a missing embedded entry does not fail EditMode tests.

Confirmed cli/release-automation's release_trigger_guard.go excludes
JSON under cli/common/ from release triggers, so no stamp update is
required for this change.
@hatayama
hatayama merged commit 5352e00 into v3-beta Jul 9, 2026
10 checks passed
@hatayama
hatayama deleted the feat/port-stream-c1-raycast-tool branch July 9, 2026 09:11
@github-actions github-actions Bot mentioned this pull request Jul 11, 2026
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