Snapping to ray in 3D

Godot Version

4.2.1

Question

I want to implement “building” into my game, i.e. letting the player place buildings in the game world. I want a building to be able to “snap” to another, such that it is easy for the player to place it at a good position.

The snapping should happen with respect to a ray. The already placed building has a certain connection point from which the ray extends into a certain direction. The player points roughly at the ray, and the building “ghost” should be snapped to the ray.

Specifically, the building should not necessarily be snapped directly to the connector on the other building, but just onto the ray, such that there may be some distance between the two. The space between them would then be filled by some sort of gangway.

Now, my question is about how to implement the snapping. I would like to do it in the way that the new building snaps to the point on the connector ray that is closest to the players cursor ray. So basically, the point on one ray that is closest to the other ray. I would be able to figure out the math for that myself, but I was wondering if I can skip this and if godot implements a function to compute the distance between two rays/straights in 3D?

That seems like pretty hard math. And probably wouldn’t scale well in a scripting language. I couldn’t find anything in Godot.

The work around would have a special invisible collision shapes just for the connector bodies that could extend out to some degree, and could compete for focus from the players ray. Then you start to use the other ray for whatever you used it for…

Another option, although I’m unsure how this could exactly work, would be to cast a shape from the player and have it collides with the other rays? Most collision expect to hit bodies and areas so maybe you need a custom shape caster that can cause collisions on your connector rays?

There is a custom cast shape function in Godot.

1 Like

Thanks! I actually also found this now on Wikipedia:

Well yeah, it may not perform perfectly, so I hope this gets added to godot at some point. But I am anyways already having a gdext library in my game, so I can just move the implementation in there.