I am making a 2D game where the player can attack enemies using a designated Area2D node as an attack area. i set up signals to manage attack phases and ensuring proper collision layers and masks, and at first it worked fine when i connected signals from the Godot editor itself, but i realized that connecting the signals via scripting is way easier since I'm gonna be duplicating the same enemy many times, but now the player can't even interact with the enemy at all and i don't know why ?
Player Script:
The player emits attack_started and attack_ended signals to manage attack phases, with the attack area's monitoring toggled accordingly.
extends Area2D
signal attack_started
signal attack_ended
export var speed = 300
var screen_size := Vector2()
var can_attack := true
var attack_cooldown := 0.5
var is_attacking := false
var swing_sound := preload("res://sound/whoosh-transitions-sfx-03-118230.wav")
func _ready():
screen_size = get_viewport_rect().size
$AttackArea.set_monitoring(false)
$AnimatedSprite.connect("animation_finished", self, "_on_AnimatedSprite_animation_finished")
$SwingSound.stream = swing_sound
$AttackArea.add_to_group("player_attacks")
func _process(delta):
handle_movement_input(delta)
handle_attack_input()
func _on_AnimatedSprite_animation_finished():
if $AnimatedSprite.animation == "attack":
$AttackArea.set_monitoring(false)
is_attacking = false
can_attack = true
func handle_movement_input(delta):
var direction := Vector2()
# Movement input handling code...
func handle_attack_input():
if Input.is_action_just_pressed("attack") and can_attack:
print("Emitting attack_started")
emit_signal("attack_started")
$AnimatedSprite.play("attack")
$SwingSound.play()
$AttackArea.set_monitoring(true)
is_attacking = true
can_attack = false
yield(get_tree().create_timer(attack_cooldown), "timeout")
$AttackArea.set_monitoring(false)
print("Emitting attack_ended")
emit_signal("attack_ended")
Enemy Script:
The enemy listens for attack_started and attack_ended signals to become vulnerable to attacks only during the player's attack animation.
extends Area2D
var vulnerable_to_attack := false
var health := 100
func _ready():
$AnimatedSprite.play("idle")
call_deferred("connect_to_player_signals")
func connect_to_player_signals():
var player = get_tree().get_root().find_node("Player", true, false)
if player:
player.connect("attack_started", self, "_on_attack_started")
player.connect("attack_ended", self, "_on_attack_ended")
func _on_EnemySoldier_area_entered(area):
if area.is_in_group("player_attacks") and vulnerable_to_attack:
$AnimatedSprite.play("hurt")
take_damage(30)
func _on_attack_started():
vulnerable_to_attack = true
func _on_attack_ended():
vulnerable_to_attack = false
func take_damage(amount):
health -= amount
if health <= 0:
die()
func die():
queue_free()
Attempts to Resolve the Issue:
*Verified that collision layers and masks are correctly set for the player's attack area and the enemy.
*Used print statements to confirm signal emission and reception.
*made sure that the attack area monitoring is set to true.
*i made sure all the variable names and things like that are exactly correct including spaces and capitalization
*made sure the nodes enter the scene in the right order
*i turned on the collision shapes being visible in game via the debug editor
I'm just not sure why it's not being detected, i checked everything from the signal connections to the node order to the names of everything to the logic to the collision shapes themselves actually being visible and intersecting via the debug editor, but i can't find the issue, I've been debugging it with chatGPT 4 but not even it knows
help is appreciated 🙂