Delay in dealing damage from enemy to player

Godot Version

4.7.2

Question

The damage it’s delayed on enemy hit the player.

Video demonstration →

Enemy scene_tree

I wonder where is culprit of this, it’s adaptation from RPG course, I’ll share relevant parts.

Animation played is → 1.3333 sec long

Animation_Tree

Enemy code to detect player ( this one seem to works fine)

func check_for_attacks() -> void:
	for collision_id in player_detector.get_collision_count():
		var collider = player_detector.get_collider(collision_id)
		if collider is Player:
			rig.travel("Overhead")
			print("player attacked")
			navigation_agent_3d.avoidance_mask = 0

signal to acknowledge the function the animation finished

func _on_animation_tree_animation_finished(anim_name: StringName) -> void:
	if anim_name == "Rig_Medium_CombatMelee/Melee_1H_Attack_Jump_Chop":
		heavy_attack.emit()

function which is responsible for calling deal_damage

func _on_rig_heavy_attack() -> void:
	area_attack.deal_damage(attack_damage, crit_rate)
	print("deal_damage called")
	navigation_agent_3d.avoidance_mask = 1
	

Area attack share for both Player and Enemy logic call take_damage inside HealthComponent.

extends ShapeCast3D

func deal_damage(damage: float, crit_chance: float) -> void:
	for collision in get_collision_count():
		var is_critical = randf() <= crit_chance
		var collider = get_collider(collision)
		if collider is Player or collider is Enemy:
			collider.health_component.take_damage(damage, is_critical)

Visual damage text is called from HealthComponent

func take_damage(damage_in: float, is_critical: bool) -> void:
	var damage = damage_in
	var damage_blocked = damage * armor_value
	damage = damage - damage_blocked
	if is_critical:
		damage *= 2.0
		VfxManager.spawn_damage_number(damage, Color.RED, body.global_position)
	else:
		VfxManager.spawn_damage_number(damage, Color.WHITE, body.global_position)
	current_health -= damage

then vfx spawns damage number on target

extends Node3D

const DAMAGE_NUMBER = preload("res://Player/damage_number.tscn")

func spawn_damage_number(damage: int, color: Color, position_in: Vector3) -> void:
	var new_number = DAMAGE_NUMBER.instantiate()
	new_number.setup(damage, color, position_in)
	add_child(new_number)

I don’t see any delay. The number pops up as soon as the animation appears to be finished, which is exactly what’s supposed to happen according to the code you posted.

would be possible to give it offset so attack is dealt a bit earlier?

Let say on 1 second instead of finished animation?

Of course. Experiment a bit and try to figure out how.

I thought about timer or call it from animation, but animation seem to be cleaner approach and quicker to experiment with.

func _emit_heavy_attack() -> void:
	heavy_attack.emit()

Yeah, using a method track is a good option.