0
\$\begingroup\$

I'm having a problem with CharacterBody2D knockback in Godot 4.3 stable.

I'm creating a game where enemies (CharacterBody2D) can get hurt and get knocked back by projectiles (also CharacterBody2D). I thought I implemented this correctly but then I realized that the knock-back sometimes pushes the enemy in the wrong direction like this :

animated .GIF showing the bug

Link to higher resolution .MP4 showing bug

The enemies usually only get knocked to the right, down and everything in between, a projectile could hit them from their right side and should push them to the left but instead pushes them to the right which makes no sense.

Here's the projectile code :

extends CharacterBody2D
class_name projectile

func _on_area_entered(area: Area2D) -> void: #the bullet enters the enemy's hurtbox
    area.get_parent().take_damage(damage_amount) #damage the enemy
    area.get_parent().knockback(knockback_force, get_velocity()) #pass the strength of the knockback and then the current Velocity of the projectile to the enemy so they can know where to get knocked back to 
    queue_free()

enemy code :

extends CharacterBody2D
class_name enemy

func _physics_process(delta: float) -> void:
    move_and_slide()

func knockback(knockback_force: int, knockback_source_pos: Vector2): #takes the strength and the source of the knockback
    var knockback_source_pos_corrected = knockback_source_pos * Vector2(-1, -1) # multiplying it by (-1, -1) makes the knockback direction less broken for some reason ?
    var knockback_direction = knockback_source_pos_corrected.direction_to(self.global_position) #this is what calculates where the enemy gets knocked to
    var knockback = knockback_direction * knockback_force #applies the strength
    
    velocity = knockback #what moves the enemy
    await get_tree().create_timer(0.2).timeout 
    velocity = Vector2.ZERO #stops the enemy after 0.2 seconds

I've tried multiplying the knockback_source_pos by (-1, 1) and (1, -1) or just leaving it as is but the knockback direction is never right.

If this whole system is just straight up bad, please tell me as I could just rewrite it from the ground up instead of patching a bad system (and I'd appreciate any advice on how to do so!) I really want learn how to create knockback for my games.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

Okay as I was falling asleep last night the solution clicked in my mind XD

and a user gave me a much better way to simplify the code too, here's the working code :

#--projectile code

func _on_area_entered(area: Area2D) -> void:
    area.get_parent().take_damage(damage_amount)
    area.get_parent().knockback(get_velocity().normalized() * knockback_force)
    queue_free()
#--enemy code

func knockback(direction: Vector2):
    velocity = direction
    await get_tree().create_timer(0.2).timeout 
    velocity = Vector2.ZERO

no need for no any .direction_to(self.global_position or * (-1, -1)

\$\endgroup\$
1
  • \$\begingroup\$ Remember to click the ✅ icon to the left to mark this answer as "Accepted" if it solved your problem. \$\endgroup\$
    – DMGregory
    Commented Nov 5 at 18:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .