Ray casting from orthogonal camera

Godot Version

4.3

I’m building a top down game with an orthogonal camera. I am trying to detect a tile when the mouse hovers over it and having issues with the detection.

The tile is an Area3D node with a 3DCollisionShape:
tile
The tiles display their position (rounded).

The camera scene is a CharacterBody3D with a Camera3D and RayCast3D nodes (the collision shape is disabled):
overhead camera

All nodes are at default position and rotation other than RayCastingCamera where rotation.X = -90 so it points downward.

GUI scene (main) is a Node3D with the overhead camera positioned at (0,8,0). The tiles are added via code at positions (x,0,z):
gui

Camera code:

public partial class OverheadCameraBody : CharacterBody3D
{
    private RayCast3D downwardRay;
    private Camera3D rayCastingCamera;
	private GodotObject detectedCollider = null;

    public override void _Ready()
    {
        rayCastingCamera = GetNode<Camera3D>("RayCastingCamera");
        downwardRay = rayCastingCamera.GetNode<RayCast3D>("DownwardRay");
    }

    public override void _Process(double delta)
	{
		detectedCollider = CastMouseRay();	
	}
	
	public override void _Input(InputEvent @event)
    {
        if (Input.IsActionPressed("selection"))
        {
            if (detectedCollider != null)
            {
                GD.Print("Selected object is: " + detectedCollider.ToString());
            } else {
                GD.Print("No collider detected");
        }
	}

    private GodotObject CastMouseRay() {
        // Getting the mouse position on the viewport
        Vector2 mousePosition = GetViewport().GetMousePosition();
        // Transalting the mouse position to world position and assigning to camera target
        downwardRay.TargetPosition = rayCastingCamera.ProjectPosition(mousePosition, Position.Y + 20.0f);
        downwardRay.ForceRaycastUpdate();
		return downwardRay.GetCollider();
	}
}

The ray’s position and target are where I expect them, and align with the position of the tiles, but the tile is not detected.

Your raycast is staying in the same place, the target position changing means it’s rotating to point in a strange direction. Try changing the ray’s position and keeping it’s target at (0, -20, 0).

Usually I raycast from the camera’s projection, even in orthogonal projections this could be helpful. Sorry for the GDScript example:

var space_state := camera.get_world_3d().direct_space_state
var query := PhysicsRayQueryParameters3D.new()

var mouse_pos := get_viewport().get_mouse_position()
var from := camera.project_ray_origin(mouse_pos)
var to := from + camera.project_ray_normal(mouse_pos) * ray_length
query.from = from
query.to = to

var result: Dictionary = space_state.intersect_ray(query)

Thanks but I’m getting the same results. I’m not sure why this is happening. The same code worked without issue when the camera was set to perspective mode. I’m thinking that I have an issue with the collisions somewhere.

After more research I found that this function does work for perspective mode:

public GodotObject CastMouseRay(){
	Vector2 mousePosition = GetViewport().GetMousePosition();
	downwardRay.TargetPosition = ProjectLocalRayNormal(mousePosition) * 20;
	downwardRay.ForceRaycastUpdate();
	return downwardRay.GetCollider();
}

But breaks in orthogonal mode:

It seems that the function reports the position of the camera instead of the mouse.

I tried a few variations on it but can’t figure it out. The internet is very sparse on this subject unfortunately.