CharacterBody2d gets stuck "randomly" even though it doesnt collide with anything

Hi amigos i have a problem with my characterbody2d. Im making a game with a monster that chases you only when the light is off (and it flickers every few seconds). The problem is that even though his collisionshape is very small and using script i checked that it doesnt collide with anything, it keeps getting stuck in “random” moments.

Do you have any idea what could cause this? Unfortunately I cant upload a video beacuse i see its not allowed but on this picture we can see that his collisionshape doesnt touches anything and even when i checked number of collisions it said 0.
image

His character body2d motion mode is set to floating and slide angle is 0. The blue on the floor is navigation layer not collision.

Monsters code: (unfortunately the forum lets me send only 1 pic so i need to put it as text)

extends CharacterBody2D


@export var speed = 500
@onready var navigation: NavigationAgent2D = $Tracker/NavigationAgent2D
@onready var animated_sprite = $AnimatedSprite2D

@onready var running_sound = $Sounds/StepsRunning
@onready var see_you_sound = $Sounds/SeeYou
@onready var sound_molest_range = $SoundMolestRange
@onready var sound_cd = $SoundCd

@onready var player_raycast = $PlayerTargetter


var target: Node2D
var last_target_pos: Vector2
var last_self_pos: Vector2
var before_last_self_pos: Vector2
#var num = 0
var ready_for_encounter_noise = false

func _ready():
	navigation.path_desired_distance = 4
	navigation.target_desired_distance = 4
	last_target_pos = Vector2(100, 100)
	before_last_self_pos = Vector2(90, 90)

func _physics_process(delta):
	#num += 1
	#print(str(Global.light_on) + "  /  " + str(num))
	if target:
		raycast_update()
		
	#if navigation.is_navigation_finished():
		#return
	var axis = to_local(navigation.get_next_path_position()).normalized()
	velocity = axis * speed
	#print(axis)
	
	
	
	#print(Global.light_on)
	if not Global.light_on:
		if axis.x > 0:
			animated_sprite.flip_h = true
		else:
			animated_sprite.flip_h = false
				
		if not running_sound.is_playing():
			running_sound.play()
		
		print("Velocity: " + str(velocity))
		move_and_slide()
		
		if last_self_pos and before_last_self_pos:
			if last_self_pos == global_position or before_last_self_pos == global_position:
				print("stuck")
				axis += Vector2(randi_range(-0.1, 0.1), randi_range(-0.1, 0.1))
				axis = axis.normalized()
				
				move_and_slide()
				
				print(get_slide_collision_count())
				for i in range(get_slide_collision_count()):
					var collision = get_slide_collision(i)
					var collider = collision.get_collider()
					print(collider)
			
			else:
				#print("LSP: " + str(last_self_pos) + "  GP: " + str(global_position))
				pass
		
	else:
		#num+= 1
		#print("stopping running sound " + str(num))
		running_sound.stop()
	
	before_last_self_pos = last_self_pos
	last_self_pos = global_position
				
	
func recalculate_path():
	#print(navigation.target_position)
	if target:
		navigation.target_position = target.global_position
		last_target_pos = target.global_position
	else:
		navigation.target_position = last_target_pos + Vector2(randi_range(-10, 10), randi_range(-10, 10))
		if abs(last_target_pos.x - global_position.x) < 50 and abs(last_target_pos.y - global_position.y) < 50:
			last_target_pos = Vector2(randi_range(20, 3000), randi_range(20, 1800))

func _on_calculate_timer_timeout():
	recalculate_path()
	#print(navigation.target_position)

func _on_aggro_area_entered(area):
	target = area.owner
	last_target_pos = target.global_position

func _on_de_aggro_area_exited(area):
	if area.owner == target:
		target = null


func raycast_update():
	#print("Raycast updates")
	player_raycast.target_position = to_local(target.position)
	if player_raycast.is_colliding():
		#print("Raycast sees something")
		var collider = player_raycast.get_collider()
		#print(collider.name)
		if (collider == target or collider.name == "TriggerArea") and ready_for_encounter_noise and Global.light_on and velocity != Vector2.ZERO:
			#print("Raycast sees the player")
			if sound_cd.is_stopped():
				sound_cd.start()
				#print("Player vision sound")
				see_you_sound.play()
			else:
				pass
				#print(sound_cd.time_left)
	

func _on_sound_molest_range_area_entered(area):
	ready_for_encounter_noise = true
	raycast_update()
	
func _on_sound_molest_range_area_exited(area):
	ready_for_encounter_noise = false`

Ok i think i solved it Il leave it there in case it will help someone.

The problem wasnt the collision with some paranormal entity it was that i used update timer set to 0,05s to update navigationagent. What it sometimes went into a loop where it didnt update fast enough and the movement was ahead of the path so it just went back to match it and it created the “being stuck” problem.

The solution was just to not use the update timer and place “recalculate_path” function in _process_physics. Its more memory taxing but i think it works.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.