get_child_count() returns 0 despite having 5 immediate children
Hey guys! I recently started doing some coding / game development as a hobby, and this is the first time I ran into a problem that I have no idea how to fix at all. Some help is desperately needed. Thanks. I have uploaded the project to Github.
What I am trying to do is a mock up of the game Raiden. I followed this tutorial for the HP display. Basically, I have a scene named HeartBar, which is a HBoxContainer at the top, and several TextureRect nodes with a heart symbol as its children. It is set to autoload, and whenever another scene Bullet hits the player, it would update HeartBar.life, after which I would set visibility of the TextureRect nodes according to how many lives I have left.
Problem: the HeartBar.life is successfully updated every time the player is hit. However, when I try to call get_child_count() in func update_health(), which is located in the HeartBar script, I get 0 instead of 5 (as I have 5 TextureRect nodes directly below).
I wonder how could I debug this problem? I only have extremely limited experience as a hobby coder in Python, so forgive me if this is really rudimentary.
I have looked at the following, but frankly speaking am too stupid to understand:
Generally speaking, I find the idea of call_deferred(), and when it is required, quite difficult to understand.
There are a couple of issues going on in this.
The main problem is that you have HeartBar as an autoload.
You also add HeartBar as a node under main scene.
What happens then is you actually have 2 HeartBars running.
I am guessing you added it as an autoload so that you can have easy access to it.
But it is actually interfering with things.
The second problem is that you don’t have main scene code.
So your game starts by running node scripts and that leads to disorganization and confusion.
I reworked things and got you to the point where
get_child_count() returns 5 here.
(Please note that this is incomplete and it is just so that you can look at the design)
I removed the autoloaded HeartBar.
I stopped the physics processes in enemy, player, and bullet from running automatically.
I also stopped the timers from auto-starting.
I added a script to the main scene and a ‘go’ button.
Clicking that button starts the player and enemy physics processes and starts the enemy firing.
You can move the ship into a bullet and see that the child count is now 5.
Instead of the bullet script calling the HeartBar it now emits a signal that the main scene code connects to. The main scene calls the HeartBar
Its left unfinished though as I left the player not shooting and there might be a print or 2 that were used in debugging.
(I also changed the screen size so I could see it all on my desktop)
Thank you sir/madam for your kind help! I didn’t expect someone to respond me so quickly, and even provided a new repository on Github. I did want to try and do this myself, and not just rely on your code, thus:
Identify my biggest problem
Duplicate HeartBar scenes: I always thought Autoload was just allowing the scene to be visited globally, as I did not know other ways to have a global variable. Disabling autoload means I have to find another way.
Lack of main scene script: I felt like this is best practice, but also something that I could add in the next version.
Reading the code
However, when reading your code, I did find the following path a bit … convoluted and unintuitive for me.
- bullet hits player
- bullet emits “player_hit”
- enemy (which instantiates the bullet) connects to player_hit, and calls “my_bullet_hit_player”, which emits “bullet_hit_player”
- main Node2D connects to bullet_hit_player, then calls heart_bar.update_health
I still preferred the singleton structure, having a global variable. Only this time, I know I should have a separate script only to store the global variable, instead autoloading the entire HeartBar scene.
Revising the code
Thus, I set out to update the code. Mainly:
- I removed the HeartBar scene from Autoload, and added a Globals scene. In its script is an integer variable “life”.
- I maintained the structure of having the bullet to emit signals when it hit the player, and added a function _on_player_hit() that reduces Globals.life by 1.
- The HeartBar script remains largely unchanged, except now it reads from Globals.life.
The updated code on Github now works correctly. (I am very unfamiliar with using Git, so hopefully I updated the code base correctly)
Thank you again for your help, especially in pointing out that I have two HeartBar scenes, which interfered with HP update.
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.