Is there an event for when a Raycast collides with an object? I've been looking all over the internet for it, but there's just no results. Please help!
There isn't. You only need to look at the official documentation on RayCast
(or RayCast2D
for that matter) to see that they don't define any signals.
What we do is check for is_colliding
on the physics frame (i.e. _physics_process
).
If you prefer a signal, we can do it by attaching an script to it. Something like this:
extends RayCast
signal collided(collider)
var last_collider:Object
func _physics_process(_delta:float) -> void:
if not is_colliding():
last_collider = null
return
var found_collider:Object = get_collider()
if found_collider != last_collider:
last_collider = found_collider
emit_signal("collided", found_collider)
You could even package it in an EditorPuglin
, so it appears as an option when adding a Node
in the editor. See Making plugins.
On the other hand, some people prefer to move away from the editor and do things from code. For that, you can always create the RayCast
add it to the scene with add_child
, and set its properties from code. Remember to call force_update_transform
and force_raycast_update
as necesary. Or even use intersect_ray
(e.g. get_world().direct_space_state.intersect_ray(start, end)
) which is a physics query that you can do at any moment, and does not require allocating a Node
.
Addendum
what if I want to call a function whenever the raycast STOPS colliding with an object?
We can use similar code to accommodate more signals. I'll overdo it for show. Remove what you don't want:
extends RayCast
signal entered(new_collider)
signal exited(old_collider)
signal collision_begin(new_collider)
signal collision_stop(old_collider)
signal collision_change(old_collider, new_collider)
var old_collider:Object
func _physics_process(_delta:float) -> void:
var new_collider:Object = null
if is_colliding():
new_collider = get_collider()
if new_collider == old_collider:
return
if old_collider == null:
emit_signal("collision_begin", new_collider)
emit_signal("entered", new_collider)
elif new_collider == null:
emit_signal("collision_stop", old_collider)
emit_signal("exited", old_collider)
else:
emit_signal("collision_change", old_collider, new_collider)
emit_signal("exited", old_collider)
emit_signal("entered", new_collider)
old_collider = new_collider
Here "entered"
behave like "collided"
from the prior example.
If you want a signal that happen when a particular object is no longer colliding, that is "exited"
. If you want a signal when no object is colliding at all, that is "collision_stop"
. I couldn't tell which case are you interested in.