Godot C# Shape Cast 3D
Shape cast detects collision objects within its designated region shape.
It can scan for multiple objects.
This page will focus on two main ways to create and use a shape cast.
A node that constantly sweeps a region of space to detect collisions.
With this node its easy to visualize exactly where the sweep region is.
To begin, create a ShapeCast3D object in your scene.
Then add a shape to your ShapeCast3D,
for example, add a box:
To check whether the shape cast detected anything we can run this code:
public override void _Process(double delta)
{
GD.Print(CollisionResult);
}
CollisionResult is an Array of dictionaries which contains all the information about the collider the shape cast detected.
For example, the next code prints all of the names of the objects that were detected by the shape cast:
public override void _Process(double delta)
{
foreach (Dictionary result in CollisionResult)
{
GD.Print(((Node3D)result["collider"]).Name);
}
}
There’s an issue with The ShapeCast3D node, where it won’t detect any colliders if its check runs through a _Ready() method:
public override void _Ready() // THIS IS BAD CODE DO NOT COPY
{
foreach (Dictionary result in CollisionResult)
{
GD.Print(((Node3D)result["collider"]).Name);
}
}
To fix this, turn _Ready() to an async method and wait for 1 frame, like this:
public async override void _Ready() // THIS IS GOOD CODE, FEEL FREE TO COPY ;)
{
await ToSignal(GetTree().CreateTimer(0),"timeout");
foreach (Dictionary result in CollisionResult)
{
GD.Print(((Node3D)result["collider"]).Name);
}
}
Note: To get different information change the “collider” string in result[“collider”].
Type | Information | Description |
---|---|---|
Vector3 | position | the position where the shapes collided. |
Vector3 | normal | which side the collided object’s surface(face) is facing. |
Object | collider | the object the shape cast detected. |
ObjectID | collider_id | object’s id |
RID | rid | object’s rid. |
int | shape | object’s shape index. |
Vector3 | linear_velocity | object’s linear velocity. |
In some cases we would need a more dynamic approach like creating the cast in code.
For example when we want to scan an area dynamically only once.
For this we can use a PhysicsShapeQueryParameters3D.
First declare the Shape3D that the ShapeCast will use:
public void Scan_Collisions()
{
var box = new BoxShape3D();
box.Size = new Vector3(1,1,1);
}
Every 3D component in godot is automatically assigned to the World3D class.
Before casting a shape we need to reference this class:
public void Scan_Collisions()
{
var box = new BoxShape3D();
box.Size = new Vector3(1,1,1);
var spaceState = GetWorld3D().DirectSpaceState;
}
spaceState represents the interactions of objects and their state in our World3D.
To represent the Shape Cast and its properties use PhysicsShapeQueryParameters3D:
public void Scan_Collisions()
{
var box = new BoxShape3D();
box.Size = new Vector3(1,1,1);
var spaceState = GetWorld3D().DirectSpaceState;
PhysicsShapeQueryParameters3D query = new PhysicsShapeQueryParameters3D();
}
Set the query’s shape:
public void Scan_Collisions()
{
var box = new BoxShape3D();
box.Size = new Vector3(1,1,1);
var spaceState = GetWorld3D().DirectSpaceState;
PhysicsShapeQueryParameters3D query = new PhysicsShapeQueryParameters3D();
query.Shape = box;
}
(Alternatively, instead of creating a shape in code, it is possible to take a shape from a separate node such as CollisionShape3D)
Finally make the query sweep for collisions in our spaceState and print it:
public void Scan_Collisions()
{
var box = new BoxShape3D();
box.Size = new Vector3(1,1,1);
var spaceState = GetWorld3D().DirectSpaceState;
PhysicsShapeQueryParameters3D query = new PhysicsShapeQueryParameters3D();
query.Shape = box;
var results = spaceState.IntersectShape(query);
GD.Print(results);
}
Note: the ‘results’ variable is the same as ‘CollisionResult’ from the previous section.
To make the query ignore a certain collider use the Exclude property.
In this example the query ignores its parent (a RigidBody3D):
RigidBody3D ignoreThis = GetParent<RigidBody3D>();
query.Exclude = new Godot.Collections.Array<Rid> { ignoreThis.GetRid() };
The exceptions array can contain objects or RIDs.
Note: the ‘GetRid()’ method only works in classes that inherit from CharacterBody3D, StaticBody3D and such.
In some cases using the Exception property could become inconvenient when excluding a lot of objects,
so instead we can use a collision mask.
In this example the query will only detect objects in Layer 1:
query.CollisionMask = 1;
More about calculating collision masks and collision layers.
In a _Ready() method, unlike a ShapeCast3D node that will not detect anything unless it waits 1 frame, this method will work and detect colliders:
public override void _Ready()
{
var spaceState = GetWorld3D().DirectSpaceState;
PhysicsShapeQueryParameters3D query = new PhysicsShapeQueryParameters3D();
query.Shape = new BoxShape3D{Size = new Vector3(1,1,1)};
var results = spaceState.IntersectShape(query);
GD.Print(results);
}
Ray Cast
RayCasting Godot
PhysicsDirectSpaceState3D
ShapeCast2D
Physics Introduction