Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Assets/Tests/Editor/RaycastToolTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ public async Task ExecuteAsync_WhenCoordinateIntersectsCollider_ShouldReturnHitA
Assert.That(response.Success, Is.True);
Assert.That(response.Hit, Is.True);
Assert.That(response.HitGameObjectName, Is.EqualTo("RaycastToolTestsCube"));
Assert.That(response.CameraName, Is.EqualTo("RaycastToolTestsCamera"));
Assert.That(response.CameraPath, Does.Contain("RaycastToolTestsCamera"));
Assert.That(response.InputCoordinateSystem, Is.EqualTo(UnityCliLoopConstants.COORDINATE_SYSTEM_TOP_LEFT_GAME_VIEW));
Assert.That(response.UnityCoordinateSystem, Is.EqualTo(UnityCliLoopConstants.COORDINATE_SYSTEM_BOTTOM_LEFT_GAME_VIEW));
Assert.That(response.CoordinateConversionFormula, Is.EqualTo(UnityCliLoopConstants.COORDINATE_CONVERSION_FORMULA_GAME_VIEW_INPUT_TO_UNITY));
Expand All @@ -101,6 +103,21 @@ public async Task ExecuteAsync_WhenCoordinateMissesCollider_ShouldReturnNoHit()
Assert.That(response.HitGameObjectName, Is.Null);
}

[Test]
public async Task ExecuteAsync_WhenCoordinateMissesCollider_ShouldStillReportResolvedCamera()
{
// Tests that the resolved Camera.main is reported even on a "No physics hit" response, so an
// agent can tell which camera the ray actually came from instead of assuming Camera.main.
CreateRaycastScene();
Vector2 inputPosition = new Vector2(0f, 0f);

RaycastResponse response = await ExecuteRaycast(inputPosition);

Assert.That(response.Hit, Is.False);
Assert.That(response.CameraName, Is.EqualTo("RaycastToolTestsCamera"));
Assert.That(response.CameraPath, Does.Contain("RaycastToolTestsCamera"));
}

[Test]
public async Task ExecuteAsync_WhenCameraIsMissing_ShouldReturnConversionMetadata()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal static GameViewRaycastResult RaycastFromInputPosition(
Camera mainCamera = Camera.main;
if (mainCamera == null)
{
return new GameViewRaycastResult(false, conversion, new RaycastHit[0]);
return new GameViewRaycastResult(false, conversion, new RaycastHit[0], null);
}

Ray ray = mainCamera.ScreenPointToRay(conversion.InjectedUnityPosition);
Expand All @@ -34,7 +34,7 @@ internal static GameViewRaycastResult RaycastFromInputPosition(
RaycastHit[] hits = Physics.RaycastAll(ray, maxDistance, visibleLayerMask);
System.Array.Sort(hits, CompareHitsByDistance);

return new GameViewRaycastResult(true, conversion, hits);
return new GameViewRaycastResult(true, conversion, hits, mainCamera);
}

private static int CompareHitsByDistance(RaycastHit left, RaycastHit right)
Expand All @@ -51,15 +51,18 @@ internal readonly struct GameViewRaycastResult
public readonly bool CameraFound;
public readonly GameViewCoordinateConversion Conversion;
public readonly RaycastHit[] Hits;
public readonly Camera Camera;

public GameViewRaycastResult(
bool cameraFound,
GameViewCoordinateConversion conversion,
RaycastHit[] hits)
RaycastHit[] hits,
Camera camera)
{
CameraFound = cameraFound;
Conversion = conversion;
Hits = hits;
Camera = camera;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace io.github.hatayama.UnityCliLoop.FirstPartyTools
public class RaycastResponse : UnityCliLoopToolResponse
{
public string Message { get; set; } = "";
public string? CameraName { get; set; }
public string? CameraPath { get; set; }
public bool Hit { get; set; }
public string? HitGameObjectName { get; set; }
public string? HitGameObjectPath { get; set; }
Expand Down
4 changes: 4 additions & 0 deletions Packages/src/Editor/FirstPartyTools/Raycast/RaycastTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ protected override Task<RaycastResponse> ExecuteAsync(RaycastSchema parameters,
noHitResponse.Success = true;
noHitResponse.Hit = false;
noHitResponse.Message = $"No physics hit at ({inputPosition.x:F1}, {inputPosition.y:F1}).";
noHitResponse.CameraName = raycastResult.Camera.name;
noHitResponse.CameraPath = GameObjectPathUtility.GetFullPath(raycastResult.Camera.gameObject);
return Task.FromResult(noHitResponse);
}

Expand All @@ -57,6 +59,8 @@ protected override Task<RaycastResponse> ExecuteAsync(RaycastSchema parameters,
response.Success = true;
response.Hit = true;
response.Message = $"Hit {nearestHit.collider.gameObject.name} at ({inputPosition.x:F1}, {inputPosition.y:F1}).";
response.CameraName = raycastResult.Camera.name;
response.CameraPath = GameObjectPathUtility.GetFullPath(raycastResult.Camera.gameObject);
response.HitGameObjectName = nearestHit.collider.gameObject.name;
response.HitGameObjectPath = GameObjectPathUtility.GetFullPath(nearestHit.collider.gameObject);
response.HitLayer = nearestHit.collider.gameObject.layer;
Expand Down