Ray-casting, extend until collision.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By julsrd

I do know that you can use Physics2DDirectSpaceState.intersect_ray() to check if there are collisions between two points. But is there a way so that the 2nd vector will extend until it hits something?

:bust_in_silhouette: Reply From: Xrayez

If you mean that you need to have an infinite ray cast, you can simulate it by casting a very long segment, you’ll need to calculate a normalized direction vector first:

extends Node2D

var direction = Vector2()
var length = 0


func _physics_process(_delta):
	# Simulate infinite ray cast.
	# In this case, we derive the size from the viewport size.
	length = get_viewport().size.length_squared()

	var from = $character.global_position
	var to = get_global_mouse_position()

	# Returns normalized direction vector.
	direction = from.direction_to(to)

	# Extend the ray in the given direction.
    # Also convert to global coordinates.
	to = (direction * length) + from

	# "Infinite" ray cast!
    var space = get_world_2d().direct_space_state
	var result = space.intersect_ray(from, to)
	var collided = not result.empty()
	print(collided)

	update()


func _draw():
	# For debugging purposes.
	var from = $character.global_position
	var to = $character.global_position + (direction * length)
	draw_line(from, to, Color.green)

But bear in mind that casting long vectors like this every frame can severely impact the performance. Instead of calculating the viewport size, you can also base this on maximum level size, for instance.

Alternatively, you can also “grow” the length of such a ray cast dynamically (from zero length to level size length, with some optimal step) and do multiple queries on each increase in length, if you find this could improve performance.