Health_Bar Array not working

Godot Version

4.6

Question

I’m trying to create an health bar system but im getting the error:
Attempt to call function ‘get_children’ in base ‘null instance’ on a null instance.

here’s my scene structure incase it’s the problem:

extends CharacterBody2D

class_name PlayerController

**@onready var health_parent: HBoxContainer = $Visuals/Health/HBoxContainer**
@onready var animation_player: AnimationPlayer = $Animation_Controls/AnimationPlayer
@onready var currenthealth: int = max_health
@onready var particles_player: CPUParticles2D = $Particles/CPUParticles2D

# Movement Variables
@export var acceleration := 2400.0
@export var speed : float = 300.0
@export var jump_force : float = -250.0
@export var jump_time : float =  0.25
@export var coyote_time : float = 0.075
@export var gravity_multiplier : float = 3.0
@export var max_health = 3

var reset_position : Vector2
var direction = 0
var is_jumping : bool = false
var jump_timer : float = 0
var coyote_timer : float = 0
var can_control : bool = true
var can_take_damage : bool = true
**var hearts_list : Array[TextureRect]**



func _ready():
	reset_position = Vector2(3.0, -63.0)
	**var hearts_parent = health_parent**
**	for child in hearts_parent.get_children():** -- THIS IS THE PROBLEM
**		hearts_list.append(child)**
**	print(hearts_list)**

**func update_hearts():**
**	for i in range(hearts_list.size()):**
**		hearts_list[i].visible = i < currenthealth**

func _physics_process(delta: float) -> void:

	if not can_control: return
	# Add the gravity.
	if not is_on_floor() and not is_jumping:
		velocity += get_gravity() * gravity_multiplier * delta
		coyote_timer += delta
	else:
		coyote_timer = 0



	# Handle jump.
	if Input.is_action_just_pressed("Jump") and (is_on_floor() or coyote_timer < coyote_time):
		particles_player.emitting = true
		velocity.y = jump_force 
		is_jumping = true
	elif  Input.is_action_pressed("Jump") and is_jumping:
		velocity.y = jump_force

	if is_jumping and Input.is_action_pressed("Jump") and jump_timer < jump_time:
		jump_timer += delta
	else:
		is_jumping = false
		jump_timer = 0


	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	direction = Input.get_axis("Left", "Right")
	velocity.x = move_toward(velocity.x, direction * speed, acceleration * delta)

	move_and_slide()


func handle_danger():
	
	currenthealth -= 1
	if currenthealth == 0:
		velocity.x = 0
		print("You Died")
		visible = false
		can_control = false
		await get_tree().create_timer(1).timeout
		reset_player()
		return

func reset_player() -> void:
	_death_animation()
	currenthealth = 3
	velocity.x = 0
	global_position = reset_position
	visible = true
	can_control = true

func _death_animation():
	var tween = create_tween()
	
	tween.tween_property(self, "light_mask",   500, 2 )

Based on this screenshot the path to the node looks correct, but since you already did it with the Sprite2D, why not use the Unique name feature instead of trying to set the correct path?
Or just do @export and set the path to the node manually, so even if you move it, you’ll still have the exact reference to it without having to manually edit said path.

i know get this: Invalid call. Nonexistent function ‘get_children’ in base ‘Nil’

What did you change exactly?

i put @export and assigned the variables

Then there’s no way that would be null. Are you sure that’s the only place where this script of yours is executed? Maybe you have it connected to another node where these variables aren’t set or your nodes are arranged differently there.

no it’s all in this one script

While your game is running, please go to the Remote tree and check how your nodes are set up.

i’ll try making the canvas layer the parent and see what alert i get

Check what’s assigned to health_parent from outside of the scene. It may override what you assign inside.

Also, is your script “global”?

1 Like

it is global

That’s your problem then. Look at the remote scene tree at runtime or do print(get_path()) in script’s _ready()

/root/Player

was the result

Only a single printout?

1 Like

yeah the problems here:

func _ready():
	print(get_path())
	reset_position = Vector2(3.0, -63.0)
	var hearts_parent = health_parent
	for child in hearts_parent.get_children():
		hearts_list.append(child)
	print(hearts_list)

func update_hearts():
	for i in range(hearts_list.size()):
		hearts_list[i].visible = i < currenthealth

i just can’t find it

Comment out the error causing line and check the printouts. Also post your remote scene tree screenshot.

1 Like

it runs with it commented out:

This doesn’t look like the Remote tree. The Remote should start with Root.

1 Like

Yeah but what is printed in the output?

This is local scene tree. We need to see the remote one that exists at runtime: