Collision with GridMaps? (C#)

Godot Version

4.3

Question

So, I’m working on a 3D Tactical RPG as my first Godot project. Using C# since I already have some experience with it, though it’s been a while since I’ve coded.

I’ve got AStar3D pathfinding and obstacle avoidance done. Now I’m trying to write a Unity-style SphereCast helper function which I’ll use for my String-Pulling algorithm. My problem is that now matter how I set up my scene or code, my SphereCast doesn’t detect my GridMap blocks.

In my MeshLibrary, each block is structured like this before exporting:

  • Node3D (.GLB mesh)

    • MeshInstance3D (child of Node3D)

      • StaticBody3D (child of MeshInstance3D)

        • CollisionShape3D (child of StaticBody3D)

I’ve set Collision Layer to 1 for all my MeshLibrary blocks and for the Gridmap itself.

Here’s my helper class (I wanted to avoid instantiating it as a Node3D, but I don’t see a convenient way to access the scene’s DirectSpaceState from a static class without passing it as a parameter):

using Godot;
using Godot.Collections;

public partial class CollisionService : Node3D
{
    private PhysicsDirectSpaceState3D Space;
    private SphereShape3D Sphere;

    public override void _Ready()
    {
        Sphere = new SphereShape3D();
    }

    public override void _PhysicsProcess(double delta)
    {
        Space = GetWorld3D().DirectSpaceState;
    }

    public Array<Dictionary> SphereCast(Vector3 origin, float radius, Vector3 direction, float maxDistance, uint collisionMask)
    {
        Sphere.Radius = radius;
        var param = new PhysicsShapeQueryParameters3D();
        param.Shape = Sphere;
        param.Transform = new Transform3D(Basis.Identity, origin);
        param.CollisionMask = collisionMask;
        param.Motion = direction * maxDistance;
        param.CollideWithAreas = true;
        param.CollideWithBodies = true;
        var result = Space.IntersectShape(param);
        return result;
    }
}

In my Pathfinding class, for now I’m just checking if there are any walls on the straight line between the player’s starting tile and the destination on. But the SphereCast never reports a collision no matter where I path from/to. I’m sure all my parameters are correct, and I’m passing “(uint)1” as the collisionMask.

Honestly, the documentation on Physics Query Parameters and IntersectShape are very confusing as a beginner since there aren’t any practical examples listed for using them. I have no idea what I’m doing wrong here. Am I not using DirectSpaceState properly? Am I using the wrong Physics parameters or Intersect function? Is there some weird idiosyncrasy with GridMaps that screws with collision?

1 Like

is The Global Transform?

I’m passing Basis.Identity since I don’t want any transforms applied to the sphereshape other than the Radius, and I’m passing in a global position for “origin” which is where I want to cast from. Am I misunderstanding the purpose of param.Transform?

Someone also pointed out that I should be using CastMotion() since IntersectShape() disregards the motion vector (I didn’t notice that when reading the docs), so I’m using that instead now and still no luck.

Welp, found out what I was doing wrong.

Since I was using an imported asset library for my MeshLibtary, my StaticBody > CollisionShape children weren’t being assigned to the proper MeshInstance. I had to right-click the imported Node3D and enable “Editable Children”. This exposes the MeshInstance that came with the asset pack, and its name will have yellow text. THAT’S what I needed to add my add my StaticBody > CollisionShape children to.

Then I deleted the old MeshLibrary, exported & re-imported it into my GridMap, and now my spherecast is properly detecting my level’s tiles.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.