Godot C# cast ray forward
Ray cast is projecting a line from one point to the other, it returns information about the closest object along its path. This page will focus on how to cast a 3D ray, how to cast a 3D ray forward from a 3D camera and how to read the ray’s result information.
Every 3D component in godot is automatically assigned to the World3D class.
Before casting a ray we need to reference this class:
public override void _PhysicsProcess(double delta)
{
var spaceState = GetWorld3D().DirectSpaceState;
}
spaceState represents the interactions of objects and their state in our World3D.
To represent the ray and its properties we will use a PhysicsRayQueryParameters3D:
public override void _PhysicsProcess(double delta)
{
var spaceState = GetWorld3D().DirectSpaceState;
var query = PhysicsRayQueryParameters3D.Create(Vector3.Zero, new Vector3(0,0,50));
}
Now we can finally cast the ray query inside our spaceState:
public override void _PhysicsProcess(double delta)
{
var spaceState = GetWorld3D().DirectSpaceState;
var query = PhysicsRayQueryParameters3D.Create(Vector3.Zero, new Vector3(0,0,50));
var result = spaceState.IntersectRay(query);
}
The result is a dictionary which contains information about the collider it collided with.
If the ray didn’t collide with anything the result will be empty.
if (result.Count > 0)
GD.Print("Hit at point: ", result["position"]);
Type | Information | Description |
---|---|---|
Vector3 | position | the position where the ray collided. |
Vector3 | normal | which side the collided object’s surface(face) is facing. |
Object | collider | the object the ray collided with. |
ObjectID | collider_id | object’s id |
RID | rid | object’s rid. |
int | shape | object’s shape index. |
int | face_index | object’s face index. |
When shooting a ray from inside an object the ray will detect its collision.
To avoid this issue we can use the Exclude property of our ray query:
public override void _PhysicsProcess(double delta)
{
var spaceState = GetWorld3D().DirectSpaceState;
var query = PhysicsRayQueryParameters3D.Create(Vector3.Zero, new Vector3(0,0,50));
query.Exclude = new Godot.Collections.Array<Rid> { GetRid() };
var result = spaceState.IntersectRay(query);
}
The exceptions array can contain objects or RIDs.
Note: the ‘GetRid()’ method only works in classes that inherit from classes like CharacterBody3D, StaticBody3D and more.
In some cases using the Exception property could become inconvenient when excluding a lot of objects, so instead we can use collision masks.
In this example we ignore layer 2:
public override void _PhysicsProcess(double delta)
{
var spaceState = GetWorld3D().DirectSpaceState;
var query = PhysicsRayQueryParameters3D.Create(Vector3.Zero, new Vector3(0,0,50));
query.CollisionMask = 4294967295 - 2;
}
Our documentation on how to calculate collision masks and collision layers.
using Godot;
public partial class RayCast : CharacterBody3D
{
[Export] Camera3D camera;
float rayLength = 1000f;
public override void _PhysicsProcess(double delta)
{
var spaceState = GetWorld3D().DirectSpaceState;
Vector3 cameraPosition = camera.GlobalPosition;
Vector3 cameraDirection = -camera.GlobalBasis.Z.Normalized();
var query = PhysicsRayQueryParameters3D.Create(cameraPosition, cameraPosition + cameraDirection * rayLength);
var result = spaceState.IntersectRay(query);
}
}
Don’t forget to set the exception property so your ray won’t intersect with your CharacterBody3D’s collision.
To get the object that the ray hit we will do:
Node obj = (Node)result["collider"];
To Get a specific type we can change ‘Node’ to something else:
GD.Print(((StaticBody3D)result["collider"]).Name);
BUT in this case if the object isn’t a StaticBody3D, this will throw an exception.
So instead of directly converting the type we can use the ‘as’ operator:
StaticBody3D staticObject = (Node)result["collider"] as StaticBody3D;
if (staticObject != null)
GD.Print(staticObject.Name);
The ‘as’ operator is a safer method, it produces a null if the object cannot be converted.
Note: to check if an object can be converted you can use the ‘is’ operator.
The ray won’t cast or it produces an error:
Make sure to cast the ray inside a _PhysicsProcess() method.
The ray casts to the side from my 3D camera:
Change the cameraDirection’s GlobalBasis.
The ray detects the player’s collision:
Set an exclusion to your ray, read the “Exclude Collision” section.
Error: ‘GetRid()’ does not exist in the current context:
Change your script’s class inheritance to CharacterBody3D or StaticBody3D etc’.
Alternatively you can reference your node as a CharacterBody3D or StaticBody3D.
Is there an easier way to calculate Layer Masks?
Not that I know of, but you can reference your CharacterBody3D’s layers/collision mask.
Sometimes I receive errors and some other times I don’t, how do I get rid of the errors?
Use if statements to validate your types.
Incase that is not an option, you can do Exception handling to ignore the errors.
Exception handling should be done only if you know what you are doing!
Godot Ray-Casting
Godot RayCast3D
Godot Collision Physics