when my mob gets hit by player detection collision with Y-sorting tiles they stop or pass through those tiles.
here is the mob code:
func _on_area_2d_body_entered(body):
player=body
player_chase = true
func _on_area_2d_body_exited(_body):
player = null
player_chase = false
Have you tried:
func _on_area_2d_body_exited(_body):
player_chase = false
player = null
If that doesn’t solve it, the problem is probably in your _process()
or _physics_process()
code for the enemy.
unfortunately it didn’t help (attached physics processes)
func _physics_process(_delta):
deal_with_damage()
if player_chase:
position +=(player.position - position)/max_speed
$AnimatedSprite2D.play("run")
if (player.position.x - position.x) < 0:
$AnimatedSprite2D.flip_h = true
else:
$AnimatedSprite2D.flip_h = false
else:
$AnimatedSprite2D.play("idle")
maybe there’s something wrong with them
Hi,
My guess would be that you have a keyframe for the position inside the idle animation.
In your video, we can see that the two mobs on the left are overlapping when in idle, which shows they’re not going through the tiles, their position is just reset by some code/animation.

Check your idle animation and make sure there’s no key for the position. If that’s not the problem, please share the full enemy code.
1 Like
it doesn’t have an animation player so i doubt it’s the animation keys
Here is its full code
extends CharacterBody2D
@onready var animated_srtite_2d = $AnimatedSprite2D
var max_speed = 70
var player_chase = false
var player = null
var health = 40
var player_inattack_zone = false
var can_take_damage = true
func _physics_process(_delta):
deal_with_damage()
if player_chase:
position +=(player.position - position)/max_speed
$AnimatedSprite2D.play("run")
if (player.position.x - position.x) < 0:
$AnimatedSprite2D.flip_h = true
else:
$AnimatedSprite2D.flip_h = false
else:
$AnimatedSprite2D.play("idle")
func _on_area_2d_body_entered(body):
player=body
player_chase = true
func _on_area_2d_body_exited(_body):
player_chase = false
player = null
func enemy():
pass
func handle_hit():
health = health - 10
print(health)
if health <=0:
self.queue_free()
func _on_enemy_hitbox_body_entered(body):
if body.has_method("player"):
player_inattack_zone = true
if body.has_method("arrow"):
player_inattack_zone = true
func _on_enemy_hitbox_body_exited(body):
if body.has_method("player"):
player_inattack_zone = false
if body.has_method("arrow"):
player_inattack_zone = false
func deal_with_damage():
if player_inattack_zone and global.player_current_attack == true:
if can_take_damage == true:
health = health - 20
$take_damage_cooldown.start()
can_take_damage = false
print("enemy health =", health)
if health <= 0:
self.queue_free()
func _on_take_damage_cooldown_timeout():
can_take_damage = true
func _on_area_2d_2_body_entered(body:Node2D) -> void:
if body.has_method("player"):
var knockback_direction = (body.global_position - global_position)
body.apply_knockback(knockback_direction,10.0, 0.12)
TBH I don’t see the issue, but I do see a lot of issues in your code. It is way overcomplicated.
- You are identifying objects by creating dummy functions inside them to identify them. Clever, but a
class_name
will do the same thing.
- You also are creating an @onready variable and then never using it - when you should be using it.
- You don’t need a
player_inattack_zone
variable that should be handled by physics masks and layers.
- Neither do you need
can_take_damage
because you don’t need to deal with damage every frame - only when it happens. And if you want to limit how quickly an enemy can take damage, change the attack rate of the player. Because swinging and nothing happening makes gameplay suck.
- The style guide recommends putting two spaces between each function. It makes readability clearer.
- You have two functions for the enemy to take damage. I deleted
handle_hit
because it is never used.
class_name Enemy extends CharacterBody2D
var max_speed = 70
var player_chase = false
var player = null
var health = 40
@onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D
func _physics_process(_delta):
if player_chase:
position +=(player.position - position)/max_speed
animated_sprite_2d.play("run")
else:
animated_sprite_2d.play("idle")
#simplified this and moved it out of the chase functionality so that your monsters will turn to look at the player when they're not chasing as well (put it back if you don't want that functionality)
animated_sprite_2d.flip_h = player.position.x - position.x < 0
func _on_area_2d_body_entered(body):
player=body
player_chase = true
func _on_area_2d_body_exited(_body):
player_chase = false
player = null
func _on_enemy_hitbox_body_entered(body):
deal_with_damage()
func deal_with_damage():
health = health - 20 #This 20 is a "magic number" and you should think about getting it from the player instead of hard-coding it here.
take_damage_cooldown_timer.start()
print("enemy health =", health)
if health <= 0:
self.queue_free()
func _on_area_2d_2_body_entered(body:Node2D) -> void:
# you need to add class_name Player to your player script for this to work
if body is Player:
var knockback_direction = (body.global_position - global_position)
body.apply_knockback(knockback_direction,10.0, 0.12)
You then need to make the arrow and the player weapon (sword or whatever) bodies and put them on a weapon layer. Then have the enemy_hitbox
Area2D have a mask only for that weapon layer and be on no layers itself. (Though TBH I would move this code to the weapons and have them be Area2Ds and detect what layer the Enemy is on and deal damage appropriately.)
After reading and refactoring your code, I believe the problem isn’t with this code. It is with apply_knockback()
which is in your Player class.
1 Like
I don’t know, maybe I misunderstood something, but now the enemy, when in contact with the player and the Y-sorting tiles, simply dies in milliseconds