How to connect the healthbar(progressbar) to enemy while the damage it takes defies in another node (damagable)

Godot Version

Godot 4

Question

so i am new to godot, and been following youtube tutorials to try it, recently i followed a 4 video tutorial to build a 2d game, now i am trying to add a health bar to the enemies (i am also looking up another tutorial) the problem is the health and damage it taken is defiend in another node called damagable

ill provide the relevent scripts

(damagable.gd) (its a child node of enemy character)

extends Node

class_name  Damagable

#@onready var healthbar = $HealthBar
signal on_hit(node : Node, damage_taken : int , knockback_direction : Vector2)
@export var dead_animation_node : String = "death"
@export var health : float = 20 :
	
	get:
		return health
	set(value):
		SignalBus.emit_signal("on_health_changed", get_parent(),value - health)
		health = value
		


func hit(damage : int, knockback_direction : Vector2):
	health -= damage
	
	emit_signal("on_hit",get_parent(), damage,knockback_direction)



func _on_animation_tree_animation_finished(anim_name):
	if(anim_name == dead_animation_node):
		get_parent().queue_free()

…
(script of healthbar.gd) (i added this as child node to enemy)

extends ProgressBar

@onready var timer = $Timer
@onready var damage_bar = $DamageBar

var health = 0 : set = _set_health

func _set_health(new_health):
	var prev_health = health
	health = min(max_value, new_health)
	value = health
	
	
	if health <= 0:
		queue_free()
		
		if health < prev_health:
			timer.start()
		else:damage_bar.value = health


func _init_health(_health):
	health = _health
	max_value = health
	value = health
	
	damage_bar.max_value = health
	damage_bar.value = health

func _on_timer_timeout():
	damage_bar.value = health

…
(this the script of enemy/(snail))

extends CharacterBody2D

@onready var healthbar = $HealthBar
@onready var animation_tree : AnimationTree = $AnimationTree
@export var starting_move_direction : Vector2 = Vector2.LEFT
@export var movement_speed : float = 30.0
@export var hit_state : State
@export var health : int

@onready var state_machine : CharacterStateMachine = $CharacterStateMachine

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")

func _ready():
	health = 20
	animation_tree.active = true
	healthbar._init_health(health)
	
	
func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y += gravity * delta


	var direction : Vector2 = starting_move_direction
	if direction && state_machine.check_if_can_move():
		velocity.x = direction.x * movement_speed
	elif state_machine.current_state != hit_state:
		velocity.x = move_toward(velocity.x, 0, movement_speed)

	move_and_slide()

First of all, it would be very helpful if you edited your post to format the code as code, so it can be read.

But, despite that, I think I get the idea. It looks like you already have an on_health_changed signal that’s emitted when you take damage.

I’m a little worried though that you seem to have health in 3 places right now, the bar, the Damagable, and the snail. Preferably only one of those would actually have the health, and given the way this code is structured it feels like Damagable is the right place for it. So then I’d have your on_health_changed signal either emit both the amount of damage and the new total amount of health, if you want, or maybe just the new total amount of health. Also, I might just call it health_changed because it’s a signal, we know it happens on_ something.

Then you can connect to that signal in your snail, which means you’ll be told when the health changes, then you just set the healthbar value to the new health value. You shouldn’t need that timer, because the code will be called only when the health changes.

Also, the healthbar probably shouldn’t be the thing that’s queue_freed when health reaches zero, that’s probably the snail. But we’ve already set it up so the snail gets told when health changes, so that would be a good place to do that. Update the healthbar, and then maybe get die.

Also, you can use the health from $Damagable.health as the initial health of the healthbar in your snail’s ready method. (Or whatever the Damagable node is called in your player’s node tree)

1 Like

thanks for the replay and information and i have edited as you said, ill look into my code to fix it :saluting_face: