Area2D enemy gets glued to the character

Godot Version

4.5.1 stable

Question

I have Area2D with CollisionShape2D on my enemy, on my characteri only have CollisionShape2D, the collision and knockback work fine, except when the enemy touches the character from the top, then it gets glued to the character and even if the speed of character is higher it’s stuck.

Can you paste any relevant code from the enemy and character scripts?
You can add ```gdscript before and ``` after the pasted code to properly format it.

no sure which is relevant, but I have this inside enemy script:

func _on_area_2d_body_entered(body):
	if body.is_in_group("player"):
		var knockback_direction = (body.global_position - global_position).normalized()
		
		if body.has_method("take_damage"):
			body.take_damage(damage, knockback_direction)

and this inside players:

func _physics_process(_delta):
	if not is_alive:
		return
# movement
	var move_direction = Vector2.ZERO
	
	if Input.is_action_pressed("move_right"):
		move_direction.x += 1
	if Input.is_action_pressed("move_left"):
		move_direction.x -= 1
	if Input.is_action_pressed("move_down"):
		move_direction.y += 1
	if Input.is_action_pressed("move_up"):
		move_direction.y -= 1
	
	if move_direction.length() > 0:
		move_direction = move_direction.normalized()
	
	var total_velocity = move_direction * speed + knockback_vector
	velocity = total_velocity
	
	var input_direction = Input.get_vector("move_left", "move_right", "move_up", "move_down")
	
	if input_direction.length() > 0:
		last_fire_direction = input_direction.normalized()
	elif Input.is_action_pressed("fire"):
		last_fire_direction = (get_global_mouse_position() - global_position).normalized()
	
	move_and_slide()
	_update_animation(input_direction, last_fire_direction)
	
	#knockback
	knockback_vector *= knockback_decay
	if knockback_vector.length() < 10:
		knockback_vector = Vector2.ZERO
	#test dmg
	if Input.is_action_pressed("take_damage"):
		take_damage(10)

func apply_knockback(direction: Vector2, force: float = 250.0):
	if direction.length() > 0:
		knockback_vector = direction.normalized() * force

func take_damage(damage_amount, knockback_direction: Vector2 = Vector2.ZERO):
	if is_invincible or not is_alive:
		return
	
	print("took", damage_amount, " damage")
	health -= damage_amount
	print("health: ", health, "/", max_health)
	
	#knockback
	if knockback_direction.length() > 0:
		apply_knockback(knockback_direction, 600.0)
	
	#invincibility
	is_invincible = true
	$AnimatedSprite2D.modulate.a = 0.5
	
	var timer = get_tree().create_timer(invincibility_time)
	timer.timeout.connect(_end_invincibility)
	
	if health <= 0:
		die()

Post the whole enemy script and character body properties as well.

extends CharacterBody2D
class_name BasicEnemy

@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D

# stats
var health: float = 30.0
var speed: float = 80.0
var damage: float = 10.0

# animation
var last_move_direction: Vector2 = Vector2.DOWN
var player_target = null

func _ready():
	await get_tree().create_timer(0.1).timeout
	var players = get_tree().get_nodes_in_group("player")
	if players.size() > 0:
		player_target = players[0]
	
	if animated_sprite:
		animated_sprite.play("side_idle")

func _physics_process(delta):
	if health <= 0:
		return
	
	if player_target:
		var direction = (player_target.global_position - global_position).normalized()
		velocity = direction * speed
		if direction.length() > 0:
			last_move_direction = direction
		update_animations(direction)
	else:
		velocity = Vector2.ZERO
		update_animations(Vector2.ZERO)
	move_and_slide()

func update_animations(dir: Vector2):
	if not animated_sprite or health <= 0:
		return
	if dir.length() > 0:
		if abs(dir.x) > abs(dir.y):
			animated_sprite.play("side_walk")
			animated_sprite.flip_h = dir.x < 0
		else:
			animated_sprite.play("front_walk" if dir.y > 0 else "back_walk")
	else:
		match animated_sprite.animation:
			"side_walk":
				animated_sprite.play("side_idle")
			"front_walk":
				animated_sprite.play("front_idle")
			"back_walk":
				animated_sprite.play("back_idle")

		if animated_sprite.animation == "side_idle":
			animated_sprite.flip_h = last_move_direction.x < 0

func take_damage(damage_amount):
	if health <= 0:
		return
	health -= damage_amount
	print("Slime health: ", health)
	if animated_sprite:
		animated_sprite.modulate = Color.RED
		await get_tree().create_timer(0.1).timeout
		animated_sprite.modulate = Color.WHITE
	
	if health <= 0:
		die()

func die():
	print("Slime died!")
	queue_free()

func _on_area_2d_body_entered(body):
	if body.is_in_group("player"):
		var knockback_direction = (body.global_position - global_position).normalized()
		
		if body.has_method("take_damage"):
			body.take_damage(damage, knockback_direction)

Character body properties, not area properties.
Also, enemy scene structure.

Motion modes for character bodies should be floating, not grounded

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