Health bar in UI not updating despite health variable changing

Godot Version

Godot 4.2.2 (Windows 11)

Question

Hi all,

Novice programmer here with a problem related to ProgressBars. In my game, the text on the health bar (ProgressBar node) doesn’t seem to change whenever the player gets damaged, it’s always at maximum (750). Here’s how the nodes are arranged:

Screenshot 2024-12-24 230206

To update the ProgressBar’s text after the player is damaged, I’ve tried setting up a global signal in my Main and Global Signal nodes…

## Main ##

[...]
	
   Globalsignals.updating_hp.connect(Callable(game_ui, "on_global_signals_updating_hp"))
## GlobalSignals ##

[...]

   signal updating_hp(updated_hp)

…which is meant to be emitted by the Player Ship whenever they take damage from a bullet (or one of their own upgrades!), decreasing the health variable (health_stat.health_stat) by the damage taken…

## Player Ship ##

extends CharacterBody2D
class_name Player

[...]

@onready var boostcharged = 1
@onready var health_stat = $HealthStat
@onready var boost_charge_time_stat = $BoostChargeTimeStat

[...]

func handle_hit(bullet_damage):
	if boosting != 1:
		if health_stat.health_stat > 0:
			health_stat.health_stat -= bullet_damage
			print("Player hit... ", health_stat.health_stat, " health remaining")
			var updated_hp = health_stat.health_stat
			Globalsignals.emit_signal("updating_hp", updated_hp)
			print("update_hp signal sent")
			return
		print("Player died...")
		#Globalsignals.emit_signal("player_death")


func _on_global_signals_self_damage_taken(self_damage_amount):
	if health_stat.health_stat > 0:
		health_stat.health_stat -= self_damage_amount
		print("Player took self damage... ", health_stat.health_stat, " health remaining")
		var updated_hp = health_stat.health_stat
		Globalsignals.emit_signal("updating_hp", updated_hp)
		print("update_hp signal sent")
		return
	print("Player died...")
	#Globalsignals.emit_signal("player_death")
## health_stat ##

extends Node


@export var health_stat: int = 750 : set = _set_state


func _set_state(new_health_stat):
	health_stat = clamp(new_health_stat, 0, 750)

This signal should be received by the GameUI control node, which should update the value and text on the health bar (ProgressBar) simultaneously…

## GameUI ##

extends Control

var score = 0
@onready var scoreLabel = $Score
@onready var health_bar = $HealthBar
@onready var healthLabel = $HealthBar/HealthText
@onready var dmg_ind_bar = $HealthBar/DmgIndBar
@onready var dmg_ind_timer = $HealthBar/DmgIndBar/DmgIndTimer

func _ready():
	scoreLabel.text = "SCORE: %d" % score
	health_bar.value = 750 # [NOTE] # 
	healthLabel.text = "HP %d" % health_bar.value

[...]

func _on_global_signals_updating_hp(updated_hp):
	print("update_hp signal RECEIVED")
	health_bar.value = updated_hp
	print("Updated HP:", updated_hp)
	healthLabel.text = "HP %d" % health_bar.value

However, the signal only seems to get stuck between Player Ship emitting it and GameUI receiving it; the print("update_hp signal RECEIVED") has never printed while I’ve been testing the code.

[NOTE] I can change the health bar’s value and text here by accessing in the same way as later on in the script - it’s weird that it doesn’t change when signals are used…

This issue has plagued me for weeks, and I’d be very grateful for some advice on how to fix it. I’m happy to give more info/code/screenshots if needed. Thank you for reading!

You forgot an “_” in the connecting line in the main script:

# Main
Globalsignals.updating_hp.connect(Callable(game_ui, "on_global_signals_updating_hp"))
# GameUI
func _on_global_signals_updating_hp(updated_hp):
	print("update_hp signal RECEIVED")
2 Likes

Just tested it after adding the _ and it works… that was simple! Thank you for being more observant than me :smiley: