"for" loop dosen't work even though it should work - please help

Godot Version

4.4.1

Question

I dont know how or why. Please ask if you need more information

For loop is exact match but only prints in the first

func ray_spell() -> void:

	var tree = get_parent().get_parent() # not really tree but is just placeholder 

	for child in tree.get_children():
		if child.name == added_spell.name:
			print("name match 1 ") # this prints everytime

	for child in tree.get_children(): # check if spell matches any child in scenetree
		if child.name == added_spell.name: # if spell matches any spell in scenetree dont add duplicate (also add a spell owner check and spell type check)
			print("name match 2 ") # this never prints
			break

		elif character.current_spell["multishot"]: # ray is cast with multishot
			print ("ray is cast with multishot") 
			character.mana -= character.current_spell["mana"]
			for i in range(multishot_count):
				var spell_instance = spell.instantiate()
				var angle_offset = -multishot_spread * 0.5 + (i * multishot_spread / max(1, multishot_count - 1))
				spell_instance.angle_offset = angle_offset
				character.add_child(spell_instance)
				added_spell = spell_instance
				break
``
		else: # spell is cast without specific spell altering attributes
			print ("spell is cast without specific spell altering attributes") 
			character.mana -= character.current_spell["mana"]
			var spell_instance = spell.instantiate()
			#print("spell instance name : ", spell_instance.name)
			spell_instance.direction = character.spell_direction.normalized()
			character.add_child(spell_instance)
			added_spell = spell_instance
			break
	print() # new line

Issue is in this piece of code. Name match 1 always prints if there is a duplicate spell while name match 2 never prints. I hope it’s something simple I’ve overlooked because I have no idea how both statements dont print

	for child in tree.get_children():
		if child.name == added_spell.name:
			print("name match 1 ") # this prints everytime

	for child in tree.get_children(): # check if spell matches any child in scenetree
		if child.name == added_spell.name: # if spell matches any spell in scenetree dont add duplicate (also add a spell owner check and spell type check)
			print("name match 2 ") # this never prints
			break

I’m guessing you’re break-ing out of the second for loop before you get to the node which has the right name. I see three break statements inside there:

  1. The first one is inside the branch which you say never executes
  2. The second is inside a third nested for loop, so that would only break out of that
  3. The last one is inside the final else branch - I’m guessing that executes for some early node.
4 Likes

I don’t think so
The “break” is only added to prevent the elif and else to trigger every time the second for loop iterates through a child.

Added_spell.name is always the string : “spell” and can only be found after the spell has been instantiated (elif or the else statement)

I think this would only happen if if child.name == added_spell.name: checks like string.contains
but shouldnt it check for an exact match?

Node setup is basically this when spell has been instantiated :

┖╴player

┠╴CollisionShape2D
┠╴Aim_sight
┃  ┠╴Path2D
┃  ┖╴CPUParticles2D
┠╴AnimatedSprite2D
┠╴AnimationPlayer
┠╴AnimationTree
┠╴Character state machine
┃  ┠╴Ground
┃  ┠╴Jump
┃  ┠╴Fall
┃  ┠╴Attack
┃  ┠╴Attack_heavy
┃  ┠╴Hurt
┃  ┠╴Death
┃  ┖╴Player_menu
┠╴spell_1_cooldown_timer
┠╴spell_2_cooldown_timer
┠╴spell_3_cooldown_timer
┠╴i_frame_timer
┠╴state_label
┠╴Camera2D
┖╴spell
   ┠╴CollisionShape2D
   ┠╴spell_raycast
   ┃  ┖╴spell_raycast_bounce

   ┠╴spell_area
   ┃  ┖╴CollisionShape2D

   ┠╴lifetime_timer
   ┠╴AnimatedSprite2D
   ┠╴CPUParticles2D
   ┖╴Label

So it should go through each child until it found the child (named spell - at the bottom) and then breaks the for loop, right?

break exits loops like for or while, so it will only ever check the first child. You could use continue, but it really doesn’t seem necessary here.

1 Like

Well, how about you add an extra print statement to see what’s going on?

for child in tree.get_children(): # check if spell matches any child in scenetree
	print("Child name: ", child.name, "; added_spell.name: ", added_spell.name)
	if child.name == added_spell.name: # if spell matches any spell in scenetree dont add duplicate (also add a spell owner check and spell type check)
		print("name match 2 ") # this never prints
		break
1 Like

Also, godot has some nice debugging features like breakpoints. You can set a breakpoint on a line of code by clicking to the left of the line number in the editor. This will produce a red circle where the breakpoint is set:

image

Then, when the game reaches that point, Godot will freeze the code and you will be able to look around. You can check out what all the variables contain, as well as continue executing the code step-by-step.

This way you can find out what is going wrong.

1 Like

I think you and @hyvernox were right and i misunderstood the answer

it did break before it was intented

Thank you!

Just out of curiosity - what did you think I was saying? I’m wondering how I could have phrased that better.

I don’t think it was in the way that you said it

The way i wanted it to work was to iterate through each child and only to trigger when it found the name match, but when i had removed the break it triggered each time it iterated. I think it sounded like I just had to remove the break statement and it would work (e.g. suggested something I already tried)

But when you suggested actually checking when the break triggered I could see that it did break prematurely and that your first answer was actually the solution.

Basically I was tired of it not working and jumped to conclusions

Alright. :slight_smile: