Issue With NPC's Marker2D's Collision Shape

Godot Version

4.3

Question

I have an NPC that has an AnimationPlayer and a Marker2D where the animations control the direction the character is facing, adjusting the Marker2D rotation accordingly. The Marker2D has a child node Area2D with a collision shape as its child for the purposes of detecting obstacles in front of the NPC.

The problem is, with my current code, as the NPC roams it checks for obstacles that are in front of it BEFORE they face a different direction, despite the animation being changed before the obstacle check in the code.

The result is if there’s an obstacle above the NPC but nowhere else, the NPC can walk through it if it was facing a different direction before moving. Also, if the NPC is facing the obstacle initially and tries to move somewhere else, it can’t. Here’s the current code:

func prepare_to_move():
	set_animation()
	
	check_for_obstacles()
	
	if !blocked:
		timer.set_paused(true)
		set_target()
		execute_movement()

func set_animation():
	if current_dir == dir.UP:
		anim.play("idle_up")
	if current_dir == dir.LEFT:
		anim.play("idle_left")
	if current_dir == dir.RIGHT:
		anim.play("idle_right")
	if current_dir == dir.DOWN:
		anim.play("idle_down")

func check_for_obstacles():
	var check = checker.get_overlapping_bodies()
	
	if check.any(func(area): return area == self):
		for i in range(check.size()):
			if check[i] == self:
				check.remove_at(i)
	
	if check.size() > 0:
		blocked = true
	else:
		blocked = false

func set_target():
	if current_dir == dir.UP:
		target_pos = Vector2(cell_x, cell_y - 1)
	if current_dir == dir.LEFT:
		target_pos = Vector2(cell_x - 1, cell_y)
	if current_dir == dir.RIGHT:
		target_pos = Vector2(cell_x + 1, cell_y)
	if current_dir == dir.DOWN:
		target_pos = Vector2(cell_x, cell_y + 1)

func execute_movement():
	var start_coord = current_pos * grid_size
	var target_coord = target_pos * grid_size
	
	var tween = create_tween()
	tween.tween_property(self, "position", target_coord, step_dur).from(start_coord)
	is_moving = true
	
	await tween.finished
	is_moving = false
	current_pos = target_pos
	cell_x = current_pos.x
	cell_y = current_pos.y
	timer.set_paused(false)

I’d like my NPC to not walk through obstacles. Any help is appreciated!

How long is the animation? I’m guessing the rotation of the Marker2D you’re using happens after the obstacle check. Consider separating the collision detection from the animation.

There’s a note in the AnimationPlayer docs play() method that suggests that the processing of the animation will not happen immediately.

A quick fix might be to apply the rotation before checking for obstacles.

Yeah the animation I believe is about a second long, but I’d tried putting rotation = x lines right after each anim.play line, to no avail. Do you think I should try putting rotation = x before the anim.play() function? I’ve also tried putting a signal at the end of set_animation() that would trigger a function that continues the move process with the obstacle check, but same result.

UPDATE: setting rotation right before each play() does not do anything different