Same code but difrent outcomes

Godot Version

4.5

Question

Two enemies use the same code. Yet only one gets the applied knockback, while the other doesn’t. It’s baffling me.

Code:

class_name CogMan
extends BaseEnemy

const SPPED: int = 2500
const FRICTION: float = 1000

@export var minSightRange: int = 4
@export var maxSightRange: int = 1000
@export var sprite_2d: Sprite2D
@export var hit_box: Hitbox
@export var nav_center: Marker2D
@export var navigation_agent_2d: NavigationAgent2D

func _ready() -> void:
	stats = stats.duplicate()
	stats.no_health.connect(death)
	hurt_box.hurt.connect(_on_hurt_box_hurt)

func _physics_process(delta: float) -> void:
	
	var state = playBack.get_current_node()
	match state:
		"IdleState": idle()
		"ChaseState": chase(delta)
		"HurtState": hurt(delta)
	

func idle():
	velocity = Vector2.ZERO

func chase(delta):
	var player = get_player()
	if player is Player: 
		navigation_agent_2d.target_position = player.global_position
		var nextPoint = navigation_agent_2d.get_next_path_position()
		velocity = global_position.direction_to(nextPoint - nav_center.position) * SPPED * delta
		sprite_2d.scale.x = sign(velocity.x)
	else: 
		velocity = Vector2.ZERO
	move_and_slide()

func hurt(delta):
	velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
	print(velocity)
	if velocity == Vector2.ZERO:
		await get_tree().create_timer(.1).timeout
		playBack.start("IdleState")
	move_and_slide()

func get_player() -> Player:
	return get_tree().get_first_node_in_group("Player")

func is_player_in_range() -> bool:
	var result = false
	var player = get_player()
	if player is Player:
		var distanceToPlayer = global_position.distance_to(player.global_position)
		if distanceToPlayer <= maxSightRange and distanceToPlayer >= minSightRange: 
			result = true
	return result

Images of each enemy to show how they are built:

What part of your code shows the knockback?

just relized it should put the base enemy code here as well

class_name BaseEnemy
extends CharacterBody2D

@export var healthDropChance: int = 20
@export var stats: Stats
@export var hurt_box: Hurtbox
@export var animation_tree: AnimationTree
@export var score: int = 100

@onready var playBack: AnimationNodeStateMachinePlayback = animation_tree.get("parameters/StateMachine/playback")

const ENEMY_DEATH_EFFECT = preload("uid://tjmftpenelwk")
const HIT_EFFECT = preload("uid://hi055p03iiak")
const HEALTH_PICK_UP = preload("uid://u2waywyamf5m")

func _ready() -> void:
	stats = stats.duplicate()
	stats.no_health.connect(death)
	if not hurt_box.hurt.is_connected(_on_hurt_box_hurt):
		hurt_box.hurt.connect(_on_hurt_box_hurt)
		

func _on_hurt_box_hurt(hitbox: Hitbox) -> void:
	Util.add_effect(self, HIT_EFFECT)
	stats.health -= hitbox.damage
	velocity = hitbox.knockback_direction * hitbox.knockback
	playBack.start("HurtState")
	
func death():
	PlayerInfo.score += score
	Util.add_effect(self, ENEMY_DEATH_EFFECT)
	if randi_range(0, 100) <= healthDropChance:
		Util.add_effect(self, HEALTH_PICK_UP)
	queue_free()

This code does the knockback itself

func _on_hurt_box_hurt(hitbox: Hitbox) -> void:
	Util.add_effect(self, HIT_EFFECT)
	stats.health -= hitbox.damage
	velocity = hitbox.knockback_direction * hitbox.knockback
	playBack.start("HurtState")

This slows the enemy down

func hurt(delta):
	velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
	print(velocity)
	if velocity == Vector2.ZERO:
		await get_tree().create_timer(.1).timeout
		playBack.start("IdleState")
	move_and_slide()

I assume this handles a signal? If so, I would make sure both enemies are listening for that signal.

i did some debugging and it seems that second enemy velocity won’t be used correctly at all. the velocity gets updated but move and slide is not using it correctly