Instantiated packed scene is showing in the scene but can't be found with code

Godot Version

4.2.2 Stable

Question

This is my remote tree from the running game, the ready function in my player spawner showing I’ve instanced my preloaded PackedScene and added it as a child to the level using call_deferrred().

Then in the _process, I’m finding and printing all children of the CharacterBody2D type which includes the Player object but that one isn’t found. Any ideas why I can’t find the player???

that line level_manager.call_deferred(“add_child”,player)
is it the one adding the player as child? if so, then the GameManager has the level_manager’s script?

also for the whole 10 seconds when the game running, it can’t detect the Player? or it’s just the first second?

Yes, the call_deferred just waits until the end of the process loop before running the add_child function to add the player as a child of Level_01 which is of type LevelManager.

The GameManager is basically an auto load just to handle my save data.

It doesn’t matter how long I wait, I’ve had it run continuously with hundreds of print statements in my output and it never picks up the player, but it picks up the Slimes.

The Slimes are included in the Level_01 packed scene which is instanced by the GameManager and when the Level_01 is loaded, the PlayerSpawner then instances the player into the level and I can move the character around in game, but still can’t seem to find it as a child of Level_01: LevelManager

remove the as Player on:

player= player_scene.instantiate() as Player 

line
so it will look like this:

player= player_scene.instantiate()

it should work with this
you are setting the type of player’s instantiate PackedScene to Player type
hence when you try to find children with CharacterBody2D type, it wont find it

Nope, didn’t work. In this test, I just ran it to print all children and it still isn’t picking up the player:

I’ll try that when I get home, but the type Player inherits from CharacterBody2D…

dont breakpoint it? if it still cant detect player after you left it for 10 seconds, then you really need a better way to get the player, not by find children

I let it run for minutes and find_children(“*”, “”, false) still doesn’t show the Player. It shows all other nodes except the player which was instantiated and not part of the level’s packed scene.

Could this be a bug of the engine that find_children() doesn’t find all current children and only those that were included in the packed scene?

possibly be a bug, but i was unable to reproduce it? can you do the Minimal Reproduction Project (MRP)?

1 Like

Here, try this: FirstGame_MRP.zip - Google Drive

So when the game is running, you can mouse over the nodes and see that some are instanced children and others are original children of the main scene (GameManager). I would think that find_child() or find_children() would be able to find it regardless of being an instanced child.

image

Why are you using call_deferred()?
Adding a node doesn’t require it.

Is there a reason you are searching for the scene instance when it is already a member of the class as player?

var player:Player 

func _ready()
    player = player_scene.instantiate()

Also, this code happens before the add_child():
player.position = spawn.position
IIRC, you have to position the node after you add it as a child or it doesn’t take.

I’m using call deferred because I was getting errors that it was busy loading other children at the same time so I just deferred.

Everything else works just fine including updating the position.

I’m not super familiar with c++ but could someone look into the add_child() function in the source code? To me, it looks like Line:835 the add_child function adds it to a children_cache but never to the actual children array.

So when node.cpp:find_children() is called and it calls it’s _update_children_cache_data(), the newly added child isn’t there.

The find_children() function has an owner parameter defaulting to true.
Change that to false.
From the documentation:

If owned is true, this method only finds nodes who have an assigned Node.owner. This is especially important for scenes instantiated through a script, because those scenes don’t have an owner.

I tested with your MRP and changing that parameter to false enabled the finding of the second child player.

1 Like

You are my hero! I didn’t realize that’s how the ownership worked. Thank you for all your help! I tested the following and it worked:

find_children("*", "Player", false, false)