Can someone direct me to where I can do a more limited version of Raycasting in a 3D project?
Working on creating some RTS like building placement but in third person. I have found some tutorials for more traditional RTS placement cameras that are using Raycasting to find the placement from Camera. However I would like to restrict the placement radius to close to the character, sort of like Engineer Sentry Placement in TF2, and I am struggling to find how to restrict it.
Heres where I am ray casting to find where the mouse is pointing and then setting the inseparables position. The Spawnable is a StaticBody3D :
func _process(delta):
if GameManager.CurrentState == GameManager.State.Building:
var camera = get_viewport().get_camera_3d()
var from = camera.project_ray_origin(get_viewport().get_mouse_position())
var to = from + camera.project_ray_normal(get_viewport().get_mouse_position()) * 10
var cursorPos = Plane(Vector3.UP, transform.origin.y).intersects_ray(from, to)
print("mouse ps:" +str(cursorPos))
CurrentSpawnable.position = Vector3(cursorPos.x, cursorPos.y, cursorPos.z)
pass>
First of all you need some reference to the Player, so that we can grab its position. You also need to define the maximum distance from the Player that you want to allow the building.
Then, in the script we need to check if the cursor position is within the defined limit and if not, lerp to be within the limit.
See below a rough implementation of that idea. I haven’t tested this code, just wrote it here raw, so in case you have any issues with it - let me know.
const RAYCAST_LENGTH = 10000.0
@export var player: Node3D
@export var max_distance: float = 5.0
func _process(delta):
if GameManager.CurrentState == GameManager.State.Building:
var camera = get_viewport().get_camera_3d()
var from = camera.project_ray_origin(get_viewport().get_mouse_position())
var to = from + camera.project_ray_normal(get_viewport().get_mouse_position()) * RAYCAST_LENGTH
var cursorPos: Vector3 = Plane(Vector3.UP, transform.origin.y).intersects_ray(from, to)
print("mouse ps:" +str(cursorPos))
var spawn_position: Vector3
var distance_to_player: float = cursorPos.distance_to(player.global_position)
if distance_to_player <= max_distance:
spawn_position = cursorPos
else:
spawn_position = lerp(player.global_position, cursorPos, max_distance / distance_to_player)
CurrentSpawnable.position = spawn_position
You’re right, distance_to_player should be a float, my mistake.
And the lerp had distance_to_player / max_distance instead of max_distance / distance_to_player.
I corrected it all now in the original script above, please try again.
I also increased the RAYCAST_LENGTH to be 10000.0, because otherwise for some reason it was less accurate.
Well, the max_distance in my code is exactly that - a radius of a sphere. Then, the lerp() function makes sure that the final position is within that radius. Mathematically it is all around a sphere, you just have to imagine it