The Character Enters In Stunned Mode Two Times, it applies the knocback efect, lately

Godot Version

4.2.2

Question

Hi, everyone, i need some help, you see, im trying to add to my game a knockback effect, like those you see in some old games, like megaman, i already posted a question about the same proyect, but I ran into another problem, the character detects the knockback two times, so what happens is that I can crash with the enemy, while I walk, he throws me back, but if I press jump, the throwing effect is applied again, this also happens if for example the enemy walks towards me, he throws me, but if I press walk, he throws me again., i dont know if is because the states of the state machine or something, like it detects, the same colision for all the states, i tried to lock it using a global boolean variable to lock this, but it dont work, this is the code of the state machine:

class_name CharacterStateMachine
extends Node

@export var rising_gravity : int = 15
@export var fast_falling_gravity : int = 20
@export var _character : CharacterBody2D
@export var current_state : State
var _states : Array[State]


func _ready():
	for child in get_children():
		if (child is State):
			_states.append(child)
			child._character = _character
		else:
			push_warning("Child " + child.name + "is not in State for this Character")
			
			
func _physics_process(delta):
	if(current_state.next_state != null):
		switch_states(current_state.next_state)
	current_state.state_process(delta)

func check_if_can_move():
	return current_state.can_move

func switch_states(new_state : State):
	if(current_state != null):
			current_state.on_exit()
			current_state.next_state = null
	current_state = new_state
	current_state.on_enter_state()



	
func check_if_can_jump():
	return current_state.can_jump
	
func check_if_is_stunned():
	return current_state.can_be_stunned

func apply_gravity():
	if(current_state.apply_gravity):
		if(!_character.is_on_floor()):
			_character.velocity.y += rising_gravity
		if(_character.velocity.y > 0):
			_character.velocity.y += fast_falling_gravity
	_character.move_and_slide()

func check_if_can_be_stunned():
	return current_state.can_be_stunned

func _input(_event : InputEvent):
	current_state.state_input(_event)

and this for example is the air state, where it detects the colision two times:

class_name AirState
extends State


@onready var lurker_enemy = get_tree().get_first_node_in_group("Enemies")
@export var brax_actions_animation_player : AnimationPlayer
@export var brax_state_machine_functions : CharacterStateMachine
@export var brax_sprite : Sprite2D
@export var idle_state : State
@export var walking_state : State
@export var attack_state : State
@export var stunned_state : State

	

func state_process(delta):
	_apply_state_gravity()
	_movement_mid_air()
	_when_on_floor_after_fall()
	
	
func state_input(_event : InputEvent):
	if (_character.velocity.y < 0 and _event.is_action_released("JUMP")):
		_character.velocity.y *= 0.5
	
	elif _event.is_action_pressed("NORMAL_ATTACK"):
		_attack()
	

func _apply_state_gravity():
	brax_state_machine_functions.apply_gravity()
	

func _when_on_floor_after_fall():
	if _character.is_on_floor():
		if _character.velocity == Vector2.ZERO:
			next_state = idle_state
		elif Input.is_action_pressed("RIGHT"):
			next_state = walking_state
		elif Input.is_action_pressed("LEFT"):
			next_state = walking_state
	

func _attack():
	brax_actions_animation_player.play("air_attack")
	next_state = attack_state
	

func _movement_mid_air():
	if brax_state_machine_functions.check_if_can_move():
		if Input.is_action_pressed("RIGHT"):
			brax_sprite.flip_h = false
			_character.velocity.x = mid_air_speed
		elif Input.is_action_pressed("LEFT"):
			brax_sprite.flip_h = true
			_character.velocity.x = -mid_air_speed
		elif Input.is_action_just_released("RIGHT"):
			_character.velocity.x = 0
		elif Input.is_action_just_released("LEFT"):
			_character.velocity.x = 0


func _on_getting_hit_body_entered(body):
	if body == lurker_enemy:
		next_state = stunned_state


func _on_getting_hit_body_exited(body):
	if body == lurker_enemy:
		can_be_stunned = false

and this one is the walk state:

class_name WalkingState
extends State




#Enemigos que seran detectados por el jugador
@onready var lurker_enemy = get_tree().get_first_node_in_group("Enemies")

@export var brax_state_machine_functions : CharacterStateMachine
@export var brax_sprite : Sprite2D


#Estados Cambio
@export var idle_state : State
@export var air_state : State
@export var dash_state : State
@export var attack_state : State
@export var stunned_state : State

@export var brax_jump_sound_effect : AudioStreamPlayer2D
@export var brax_actions_animation_player : AnimationPlayer



func state_process(delta):
	_apply_state_gravity()
	_walk()
	_stop_walk()
	_after_falling_of_a_platform()
	_attack_while_walking()


func state_input(_event : InputEvent):
	if (_event.is_action_pressed("JUMP") and brax_state_machine_functions.check_if_can_jump()):
		_jump()
	
	if (Input.is_action_pressed("RIGHT") and _event.is_action_pressed("DASH")):
		next_state = dash_state
	
	if (Input.is_action_pressed("LEFT") and _event.is_action_pressed("DASH")):
		next_state = dash_state
	
	
func _walk():
	if brax_state_machine_functions.check_if_can_move():
		if Input.is_action_pressed("RIGHT"):
			brax_sprite.flip_h = false
			_character.velocity.x = walk_speed
		if Input.is_action_pressed("LEFT"):
			brax_sprite.flip_h = true
			_character.velocity.x = -walk_speed
		
		
func _stop_walk():
	if (Input.is_action_just_released("RIGHT") and not _character.velocity.x < 0):
		_character.velocity = Vector2.ZERO
	elif (Input.is_action_just_released("LEFT") and not _character.velocity.y > 0):
		_character.velocity = Vector2.ZERO
	
	elif _character.velocity == Vector2.ZERO:
		next_state = idle_state
	
	
func _apply_state_gravity():
	brax_state_machine_functions.apply_gravity()
	

func _after_falling_of_a_platform():
	if _character.velocity.y > 0 :
		next_state = air_state
		
		
func _attack_while_walking():
	if Input.is_action_just_pressed("NORMAL_ATTACK"): #Detener el movimiento mientras brax ataca al moverse
		_character.velocity.x = 0
		next_state = attack_state
	
	
func _jump():
	brax_jump_sound_effect.play()
	_character.velocity.y = base_jump_height
	next_state = air_state

func _on_getting_hit_body_entered(body):
	if body == lurker_enemy:
		next_state = stunned_state


func _on_getting_hit_body_exited(body):
	if body == lurker_enemy:
		next_state = idle_state

i would appreciate the help, seriously, thanks

Shouldn’t this return current_state.stunned_state?

Maybe I am missunderstanding this func, it seems odd to have two func that return the same thing.

Yeah, you see that function was to detect if the can be stunned variable was true, then the state is changed to stunned, but, yeah that din´t worked, so i added differents area2d for every state on the character, that way, i can disable and enable the area2d when needed, i dont know if that is the best way, but it worked