Godot Version
4.3
I am building a top down, tile based strategy game. The camera is placed in a fixed height looking down at the board and is controlled by a gamepad.
Goal: The player can select the tile that the camera is hovering over.
I’ve simplified the project to the components which are relevant to the problem:
- ‘BaseTile’ is of type Area3d
- Node ‘TileCollision’ of type CollisionShape3D
- Node ‘HexRim’ of type Node3D. This is an imported mesh
Both with default Transform
using Godot;
using System;
public partial class BaseTile : Area3D
{
public override void _Ready()
{
GD.Print("Tile position:" + Position.ToString());
}
}
- 'Map; is type Node3D
- Node ‘OverheadCameraBody’ of type ‘CharacterBody3D’, default Transform.
- Node ‘RayCastingCamera’ of type ‘Camera3D’. Defualt Position. Rotatio (-90,0,0) so it looks down at the board.
- Node ‘DownwardRay’ of type ‘RayCast3D’. Default Transform.
- Node ‘DisabledCollision3D’ of type ‘CollisionShape3D’. It’s here to stop Godot from bitching. It’s disabled so shouldn’t interfere with the ray.
- Node ‘CameraPositionMarker’ of type ‘MeshInstance3D’. Position (0,-2,0). This provides a sort of a cursor to see where the camera is.
- Node ‘Tile’ Of type ‘BaseTile’. Default transform.
using Godot;
using System;
public partial class RayCastingCamera : Camera3D
{
private RayCast3D downwardRay;
private GodotObject detectedCollider;
public override void _Ready()
{
downwardRay = GetNode<RayCast3D>("DownwardRay");
GD.Print("Downward ray ready: " + downwardRay.ToString() + "; Enabled: " + downwardRay.Enabled);
}
public override void _Input(InputEvent @event)
{
if (Input.IsActionPressed("selection"))
{
GD.Print("Camera position:" + GlobalTransform.Origin.ToString());
GD.Print("Target position: " + downwardRay.TargetPosition.ToString());
if (detectedCollider != null)
{
GD.Print("Selected object is: " + detectedCollider.ToString());
}
}
}
public override void _Process(double delta)
{
Vector3 camera_position = GlobalTransform.Origin;
Vector3 downward_direction = new Vector3(0, -1, 0); // Vector pointing downward
downwardRay.TargetPosition = camera_position + downward_direction * 30;
downwardRay.ForceRaycastUpdate();
GodotObject detectedCollider = downwardRay.GetCollider();
}
}
On start up, I see this message as expected:
Downward ray ready: <RayCast3D#28991030576>; Enabled: True
Tile position:(0, 0, 0)
The marker is at the centre of the tile:
When triggering ‘selection’ the message:
Camera position:(0, 20, 0)
Target position: (0, -10, 0)
But the collider is not detected. I can see that the tile is at (0,0,0), and the ray is passing between (0,20,0) and (0,-10,0) so why isn’t it reporting the collision?