how do i remove health from my tracked target

So i am currently working on a 2D TopDown Base Defense game where the Player can spawn creatures and has to fight off waves.
I want my units to focus on the closest target and remove some HP when they are in range of my raycast2d.
Tracking of and moving to the targets works perfectly, the targets have a var called “HEALTH”.

my code currently looks like this:

when i run this code and let two units collide i get:

  • Invalid get index ‘HEALTH’ (on base: ‘Nil’)

printing “curr_tar” gives me:

  • enem1:<CharacterBody2D#32715572656>

I thought about usind a Hitbox in my animation but I only want the tracked target to lose health wich I dont know how to do with a hitbox.

pls help

This has happened to me. If you queue_free() when their HEALTH is at 0, the script may run once more and cause NIL values. I am not to sure this is exactly happening, but to solve it try the following:

if curr_tar != nil and HEALTH <= 0

For future questions, it helps if you paste the code as text in a code block. I hope this works for you!

1 Like

you are right with the problem being the queue_free() but when I try your recommendation it says “identifier ‘nil’ is not declared in the current scope”

1 Like

I’m sorry, replace nil with null.

1 Like

Sorry for the late answer, had some exams to do…
i figured i can solve the problem by putting my base in the enemy_troops group. the Problem i have now, is that my code sets every enemy_troops Health to 0 so when i have the first encounter every enemy including the base dies. you have an idea how to fix that?

Could you paste the code? make sure to use three ticks for formatting, ctrl+e or the </> button in the forum editor can make these for you

```
type or paste code here
```

I don’t think your first screenshot included the line the first error appeared on, make sure to also point out which line exactly raises an error. Showing the stack trace is a huge help too

thats the code:

extends CharacterBody2D

@onready var animated_sprite_2d = $AnimatedSprite2D
@onready var ray_cast_2d = $RayCast2D

const SPEED = 50
var MOVEMENT = SPEED
var HEALTH = 100
var ATTACK = 25
var MOTION = Vector2.ZERO

func _physics_process(delta):
	var curr_tar : Node2D
	var targets : Array = get_tree().get_nodes_in_group("enemy_troops")
	if targets:
		var shortest_distance : float = global_position.distance_to(targets[0].global_position)
		curr_tar = targets[0]
		for i in targets:
			var curr_dist : float = global_position.distance_to(i.global_position)
			if curr_dist < shortest_distance:
				curr_tar = i
				shortest_distance = curr_dist
		position = position.move_toward(curr_tar.global_position, delta * MOVEMENT)
	print(curr_tar)
	if ray_cast_2d.is_colliding():
		MOVEMENT = 0
		animated_sprite_2d.play("attack")
		curr_tar.HEALTH -= 100
	else:
		MOVEMENT = SPEED
		animated_sprite_2d.play("run")

	#DEATH
	if HEALTH <= 0:
		queue_free()

I solved the error from before but my code removes health from every Node in the enemy_troops group

I think your code has logic error. In every _physics_process(), your code finds out nearest enemy and kills it. But it is very fast. Just imagine, you have 10 enemies. In first _physics_process() call, third enemy died. Just after that, fourth enemy died. And so on. Could you just try it with a timer? Maybe you should kill enemies in timer’s timeout function rather than _physics_process() (which costs more performance than timer).