Problem with changing state by using enum state

Godot Version

<stable4.2>

Question

<Im using enum state to make boss for 2d platformer. Right now, boss has three state which are IDLE, CHARGE, and RUSH. it will start with IDLE state and after 3 secs, it will enter to CHARGE state which make boss to move backward. after 1 sec in CHARGE state, boss will enter RUSH state, which does move forward in constant speed until it hit wall three times and stops at nearest Marker2d. The problem arise when boss enter RUSH state. I have no idea why but when boss enter RUSH state, it will go back to CHARGE state irregularly. I would really really appreciate if you could give me a hand to identify the cause of problem and solve it.

enum States {IDLE, CHARGE, RUSH}
@onready var state: States = States.IDLE


func _physics_process(delta):

	match state:
		States.IDLE:
			print("IDLE")
			$AnimationPlayer.play("idle")
			if direction == 1:
				$Marker2D.scale.x = -1
			elif direction == -1:
				$Marker2D.scale.x = 1
			velocity.x = 0
			velocity.y = gravity * delta
			move_and_slide()
			await get_tree().create_timer(3.0).timeout
			state = States.CHARGE
		States.CHARGE:
			print("CHARGE")
			$AnimationPlayer.play("charge")
			velocity.x = charge_speed * -direction
			charge_speed *= 0.95
			velocity.y = gravity * delta
			move_and_slide()
			await get_tree().create_timer(1.0).timeout
			state = States.RUSH
		States.RUSH:
			print("RUSH")
			$AnimationPlayer.play("rush")
			charge_speed = initial_charge_speed
			if direction == 1:
				$Marker2D.scale.x = -1
			elif direction == -1:
				$Marker2D.scale.x = 1
			velocity.x = rush_speed * direction
			velocity.y = gravity * delta
			move_and_slide()
			if is_on_wall():
				print("wallhit:", wallhit_count)
				direction *= -1
				wallhit_count += 1
			if wallhit_count >= max_wallhit:
				stop_at_nearest_position()


func stop_at_nearest_position():
	var left_distance = $Marker2D2.global_position.distance_to(stop02.global_position)
	var right_distance = $Marker2D2.global_position.distance_to(stop01.global_position)
	if left_distance < right_distance: #if left is nearest
		print("STOP AT LEFT")
		if $Marker2D2.global_position.x > stop02.global_position.x:
			print("STOP")
			wallhit_count = 0
			state = States.IDLE
	elif right_distance < left_distance:
		print("STOP AT RIGHT")
		if $Marker2D2.global_position.x < stop01.global_position.x:
			print("STOP")
			wallhit_count = 0
			state = States.IDLE
1 Like

Hey

My guess would be that awaiting in a _process function might be the cause of your issue

See the _process builtin will be called periodically

Another instance of the method might be called while you are still waiting, effectively queueing your await and leading to weird behavior

Hope it helped!

Thank you notcampeur!
I decided to change state by

func change_state(new_state: int):
	if state != new_state:
		state = new_state

right now, this works. let me know if there is any better way to change state.