Raycast2D Collider is Null unless player is in specific spot

Godot Version

4.2.1

Question

I’m getting a weird bug with my RayCast2D, the target position updates fine but for some reason the collider is Null unless the player is in a particular area. I gave it a collision mask that ONLY interacts with the player currently, so there should be nothing colliding before the player regardless of the position.

I made this enemy in a separate project and didn’t have this issue so I am pretty confused. GitHub - captaincainer/RaycastProjectileMob

extends Enemy
class_name Red_Ninja

signal health_changed
signal see_player_signal
signal lost_player_signal

@onready var ray_cast: RayCast2D = $RaycastAtPlayer
@onready var attack_timer: Timer = $AttackTimer
@onready var player_detection: Timer = $PlayerDetection
@onready var player: Player = get_parent().get_child(0).get_child(0) #THIS IS FOR ALL ACTUAL LEVELS
@onready var shuriken: PackedScene = preload("res://Characters/Enemies/Red Ninja (Ranged)/shuriken.tscn")

var see_player: bool = false


func _ready() -> void:
    $Sprite2D.visible = true
    health_bar.visible = false


func _process(delta: float) -> void:
    print_debug(ray_cast.target_position)
    _aim()
    _check_player_collision()


func _aim() -> void:
    ray_cast.target_position = to_local(player.position)


func _check_player_collision() -> void:
    if ray_cast.get_collider() == player and attack_timer.is_stopped():
        attack_timer.start()
        see_player = true
        print_debug(see_player)
        emit_signal("see_player_signal")
    elif ray_cast.get_collider() != player and not attack_timer.is_stopped():
        attack_timer.stop()
        see_player = false
        print_debug(see_player)


func _on_attack_timer_timeout() -> void:
    _shoot()


func _shoot() -> void:
    var bullet = shuriken.instantiate()
    bullet.position = global_position
    bullet.direction = (ray_cast.target_position).normalized()
    get_tree().current_scene.add_child(bullet)
![image|690x229](upload://8GuaiFeJ9pWvQ07zaEIVfx3rUbS.png)


func _on_hurtbox_area_entered(_area: Area2D) -> void:
    if mercy_timer.time_left > 0: 
        return
        
    current_health -= 1
    
    if current_health <= 0:
        emit_signal("enemy_dead")
        queue_free()
    animation_player.play("dummyAttacked")
    health_changed.emit()
    health_bar.visible = true
    mercy_timer.start(damage_cooldown)

In the video below if the arrow is red then the collider is the player, however if the arrow is blue then the collider is null. Please let me know if additional information is needed, thanks!

Edit: The required positioning of the player is the same regardless where the enemy is positioned and regardless of the scene.

Dttf-ezgif.com-video-to-gif-converter


image

player is up then first then first, but in your “TestLevel” tree that’s not “Player,” thats “FSM”.
I don’t know if that matters, but it might.
That’s the only thing I can see that might be unexpected.

my guess is, you will need force_raycast_update

Oh dang, I didnt realize I erased the whole line, I was editing the script on here, but in my actual code there is another player onready var that is used in the test level. You can see it in the turret screenshot.

Interesting, why do you think that I need that in my game but not the side project where I built this out first? The desired functionality exists fine in the prototype project without that.

The ray is clearly updating as seen from the correct visualization. If you post the project files I can take a look.

I will make the repo public during my lunch break from work, alternatively you can DM me your email and I can add you as a contributor.

Thank you TONS!

I made the repo public, thank you for your help!

I just did a stable push and left notes in a readme for you

1 Like

You’re gonna be sad, because the reason is very silly.
I made the CollisionShape2D the Player object uses be red (and added a test label).

The ray targets the center of the player, but the CollisionShape2D has a box shape that does not cover the center of the player. That’s why the ray fails to match anything unless the player is above the enemy. It is stopping before it reaches the player’s shape.

You could aim the ray at the feet or make the player shape slightly taller.

WOW, I am going to test this right now (totally not on the clock at work >_>)

Wow, that is HILARIOUS! Thank you so very much, I hope you have a wonderful weekend :slight_smile:

1 Like