To push your “Hurtbox” along with your character when your 'Hitbox " collides with it, you can add a knockback effect in the “on_area_entered” function,
Knockback Logic: Calculate the knockback direction based on the positions of the "Hitbox "and “Hurtbox”.
Apply Knockback: Use “apply_central_impulse()” on the “Hurtbox” (assuming it’s a RigidBody2D) to apply the knockback force.
for example–
class_name HitboxHandler extends Area2D
@export var damage: int = 0
@export var knockback_power: float = 0.0
func _ready() -> void:
area_entered.connect(on_area_entered)
func on_area_entered(area: Area2D) -> void:
if area.has_signal("on_hit"):
# Handle damage
area.health_handler.handle_damage(damage)
area.on_hit.emit()
# Apply knockback
if area is RigidBody2D:
var direction = (area.global_position - global_position).normalized()
area.apply_central_impulse(direction * knockback_power)
This approach will allow your Hitbox to push the “Hurtbox” when they collide.
Hi.
If for some reason Ethan’s solution doesn’t work/apply, or your player is a CharacterBody2D (only RigidBodies have apply_central_impulse) here’s how you can do it on the CharacterBody2D default script.
This is yout Hitbox:
class_name HitboxHandler extends Area2D
@export var damage : int = 0
func _ready():
area_entered.connect(on_area_entered)
func on_area_entered(area : Area2D):
if area.has_signal("on_hit"):
area.on_hit.emit(damage, self)
This is the Hurtbox.
class_name HurtboxHandler extends Area2D
@export var health : int = 100
signal on_hit(damage : float, hitbox : Area2D)
signal apply_knockback(hitbox : Area2D)
func _ready():
on_hit.connect(_on_hitbox_hit)
func _on_hitbox_hit(damage : int, hitbox : Area2D):
#manage damage animations and death signals here (I'm simplifying)
health -= damage
#sends the knockback signal to the player,
#hitbox param is to define the direction of the knockback
apply_knockback.emit(hitbox)
And this is your CharacterBody2D default script modified so it handles the knockback.
extends CharacterBody2D
const SPEED = 300.0
const JUMP_VELOCITY = -400.0
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var knocked_timeout = 0
var knockback_power : float = 200
@onready var player_hurtbox = $PlayerHurtbox
func _ready():
player_hurtbox.apply_knockback.connect(_player_apply_knockback)
func _physics_process(delta):
# Add the gravity.
if not is_on_floor():
velocity.y += gravity * delta
if knocked_timeout > 0:
#for a certain timeout the player can't move the character or jump
knocked_timeout -= delta
else:
# Handle jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var direction = Input.get_axis("ui_left", "ui_right")
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
move_and_slide()
func _player_apply_knockback(enemyHitbox: Area2D):
var knockback_direction : Vector2 = Vector2(1, -1).normalized()
if (enemyHitbox.position.x > position.x):
knockback_direction.x *= -1
velocity = knockback_direction * knockback_power
knocked_timeout = .4
Of course I simplified a lot of things, I just wanted to give you the basic structure for how you can do it.
This is the scene setup:
And here’s the result:
Hope it helps you (or someone who bumps into this question and needs to do it with a CharacterBody2D).