Instance not valid when node is instanced through code

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Darxkl05

What happens is that I’m instancing a node as a child of another one through code using add_child. This is part of my inventory system, as the instanced node appears when getting an item. In order to instance the node I’m using the following function:

func ObjectToInventory(slot, item_name, texture_to_load):
	slot.add_child(InventoryItemInstance)
	slot.get_node("Item1").name = item_name
	slot.get_node(item_name).ItemTexture = load(texture_to_load)
	slot.get_node(item_name).texture_normal = load(texture_to_load)

ObjectToInventory(item_slots, "LEDTubeLight", "res://Textures/UI/InventoryImages/LEDTubeLight.png")

(InventoryItemInstance is the node I want to instance, which was defined before:

var InventoryItemScene = preload("res://Scenes/Assets/UI/InventoryItem.tscn")
var InventoryItemInstance = InventoryItemScene.instance()

This part of the code works perfectly, the problem is that the node is a button, and it doesn’t seem to work when instancing it through code. The issue is not from the node itself, as I tried adding it through the editor, and it worked.

I also checked the remote tab, and the node was instanced correctly.
Before getting the item:
enter image description here

After getting the item:
enter image description here

I used is_instance_valid() to check if the node was instanced correctly, by printing something if it’s valid. When I add the node from the editor, the instance is valid, but when it’s added through code, it doesn’t seem to be, as nothing is printed.

Any help would be appreciated

Try to use the static-typing and activate all the warnings (Project Settings>Debug>GDscript>Warnings).
See if you get some warnings about sub-class using.

mrfatalo | 2022-08-18 13:02

:bust_in_silhouette: Reply From: CassanovaWong

Maybe just add the initial instance in the editor, hidden. Then, when you need to instance the node, just duplicate the initial instance and make it visible. I dunno if I understood your dilemma… but I know this may offer you a work around.

This suggestion usually works for me

godot_dev_ | 2022-08-18 14:58

I thought of doing at first, but I need to check how many children there are in the node to set a maximum amount of items to the inventory.

Will it work if I create the nodes separately but put them in another node as invisible? If so, how can I move those nodes to the actual inventory slots? For instance, if I store those invisible nodes as children of another node called InventoryItemQueue, how can I move them to another node called ItemSlots?

Darxkl05 | 2022-08-18 21:34

This post explains how to reparent a node via scripting. If you store invisible children, you may want to store them as children of a parent of type Node, and make sure when you reparent the children to make them visible

godot_dev_ | 2022-08-19 15:39

:bust_in_silhouette: Reply From: Inces

You predefined both class and instance. Because of this, your Objecttoinventoryfunction can only work once, as it adds child of this first predefined instance. Every time after that, it should throw an error, that this instance is already childed.
All You need to do is to instantiate object inside a `Objecttoinventory as a first line, and remove predefined instance.

:bust_in_silhouette: Reply From: Darxkl05

I figured out the solution, I only had to put a variable to the button texture inside of physics process (delta) instead of at the beginning.
Instead of doing

onready var LEDTubeLight = item_slots-get_node("LEDTubeLight)

I had to do:

func _physics_process (delta):
     var LEDTubeLight = item_slots-get_node("LEDTubeLight)