GODOT3, how RayCast2D node work

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


I have a quite simple task to do, if an enemy see the character of the player, the enemy move toward the character, and I want to do it with RayCast2D node inside the enemy scene, so I can detect obstacles between character and enemy

I wrote these lines of code for the enemy so that at every physic process frame the ray is cast toward the player´s character:

var idle=true
var player_detected=false
var target=global_position
func _physics_process(delta):
if ($RayCast2D.is_colliding()==true and $RayCast2D.get_collider().get_parent()==character):
		print("I see you")
	elif player_detected==true:
		print("I cant see you but i remember where you were")
move_toward(target,delta)    #a simple function to move the enemy

This is not working, the player is detected only if the character stands in front of the enemy. I suppose the .set_cast_to() command is not working as intended, and that detection happens only if the character move inside the original ray I created into the enemy scene.
What am I doing wrong here?

it turned out the input for the command “cast to” is always refereed in local coordinates, which means that if you instance the scene with the RayCast2d in a world scene, if the scenese rotates or move, it is very difficult to calculate the correct casting Vector2.
It is much easier to create a very long RayCast, and then set it´s rotation so that is always pointing toward the player.
if I substitute $RayCast2D.set_cast_to(character.global_position) with $RayCast2D.rotation=get_angle_to(character.global_position)it works fine.

PS: (may I say that to use local coordinates to cast a ray is quite silly? It´s very likely a ray is used to get collision between objects of different scenes with different local coordinates. Is there a way to take that into consideration without let me doing hard trigonometry problems?)

thank for this random thread from 2 years ago solved my problem

illuminae | 2020-06-23 17:23

:bust_in_silhouette: Reply From: rustyStriker

Ok, so first of all the raycast2D works like a laser pointer, and will return the FIRST object it collides with.
second of all, if you set cast_to to Vector2(0,1) and then rotates it by 90 degrees its like you made the cast_to to Vector2(-1,0) .
third of all, the get_collider() returns the physics object not the collider itself( if you dont trust me just print the collider’s name or seomthing ).
FOURTH: if you have a Boolean in an if statement you dont need to ask if its true, its like saying if true == true or if false == true(i think you get the point here)
fifth: setting the cast_to doesnt mean it will cast towards that point from where it stands but if will cast to that vector from where it stands, if the raycast will stand in (0,10) and its cast_to is (10,0) the end of it will be relative to its position so globally it will the point (10,10), you want to set it to the relative position, so it will be $Player.global_position - $Raycast.global_position.

no sixth sorry but here is the word potato: potato

Already tried that, didnt work.
That´s because if you do difference=player.global_position - $raycast.global_position, it will take into account the difference in translation, but not in rotation: if the scene with the ray rotates, casting the ray toward said difference will point toward a totally wrong direction. In order to take in account difference in translation AND rotation you have to rotate the vector of the difference so that it nullify the rotation of the scene in which the Raycast2d is living (and this is where my question about hard trigonometry came from. not really that hard, but i cannot imagine there is not a simpler way)

Andrea | 2018-03-01 02:08

the difference is a 2d Vector right? so try getting the length using Vector2D.length() and place that length in the Y axis of the cast_to vector( i think it should be in the y )…

and for what you think about raycasts, you are kinda wrong, you can use them to do some lasers, use them for a “scanner”, to shoot a bullet without shooting the bullet(like in cs go, no bullet physics)… and for geometry, its the easiest of geometry possible, and if you want some help with it take an eraseable marker and some invisible slides to draw on(like in the new minutephysics video) and draw lines and rotate and move them around, you will get it in no time if you will visualize it for yourself… dont be afraid to use probs to understand better(its actually fun when you learn and understand it properly)

rustyStriker | 2018-03-01 16:52

Mmmmh… not sure I understood: you want me to try with$RayCast2D.cast_to(0,difference.length()) ? won´t this ray simply point down relatively to the enemy (regardless of the position of the player)?

Andrea | 2018-03-02 03:23

it will point down the distance from the player, and since you rotate it to the player then it will rotate to the player(so if the distance is,in geometrical vectors,(20 units, 30 degrees) you will have a raycast pointing 20 units down,which if i recall correctly is the 0 degrees position, you will have a 20 units raycast at 30 degrees, resulting in pointing towards the player)

rustyStriker | 2018-03-02 11:48

Maybe I express myself badly: the enemy do not always face the player, it face it only when it sees him. However, in order for it to sees him, a raycast must ALWAYS be cast from the enemy to the player, independently from enemy-player relative position and rotation

Andrea | 2018-03-05 02:52

well, you can rotate only the Sprite instead of the whole scene if the enemy is round

rustyStriker | 2018-03-05 05:52

Lol, but then the problem is reversed to find the correct angle for the sprite, knowing the scene is always rotated toward the player XD
But that´s ok, i´m quite satisfied with my solution already! Thank you for your help anyway! :slight_smile:

Andrea | 2018-03-05 06:04