What is the correct way to create and delete instances of a scene without leaving behind references?

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

High Level Goal:
I have a scene I’d like to instance into and out of the main scene repeatedly. While the instance is in the scene, there should be a global reference to it so that functions of the instance can be called through that reference.

Details:
I create a global variable that holds the reference to the instanced scene.

var instance
var scene = preload("path to scene")

func _ready():
    instance = scene.instance()
    instance.setProperty(...)
    add_child(instance)

func onSignal():
    # a callback on a certain signal, time to clean up and create a new scene instance
    createNewInstance()

func changeInstance1():
    # a function that runs a function of the scene instance using the global reference
    instance.doSomething()

func createNewInstance():
    instance.queue_free()
    instance = scene.instance()
    instance.setProperty(...)
    add_child(instance)

That’s my setup. But I think this is wrong because, the game freezes after a while. A little investigation showed me that the memory usage is really high. If I change createNewInstance() to:

func createNewInstance():
    print("In function createNewInstance()")
    print(instance)
    instance.queue_free()
    print(instance)
    instance = scene.instance()
    instance.setProperty(...)
    add_child(instance)

The first time it prints this:

[Node2D:983]
[Node2D:983]

but the second (or later) time it prints this out of nowhere:

In function createNewInstance()
[Node2D:2004]
[Node2D:2004]
In function createNewInstance()
[Node2D:2049]
[Node2D:2049]
In function createNewInstance()
[Node2D:2070]
[Node2D:2070]
In function createNewInstance()
[Node2D:2091]
[Node2D:2091]
In function createNewInstance()
[Node2D:2112]
[Node2D:2112]
In function createNewInstance()
[Node2D:2133]
[Node2D:2133]
In function createNewInstance()
[Node2D:2154]
[Node2D:2154]
In function createNewInstance()
[Node2D:2175]
[Node2D:2175]
In function createNewInstance()
[Node2D:2196]
[Node2D:2196]
In function createNewInstance()
[Node2D:2217]
[Node2D:2217]
In function createNewInstance()
[Node2D:2238]
[Node2D:2238]
In function createNewInstance()
[Node2D:2259]
[Node2D:2259]
In function createNewInstance()
[Node2D:2280]
[Node2D:2280]
In function createNewInstance()
[Node2D:2301]
[Node2D:2301]
In function createNewInstance()
[Node2D:2322]
[Node2D:2322]
In function createNewInstance()
[Node2D:2343]
[Node2D:2343]
In function createNewInstance()
[Node2D:2364]
[Node2D:2364]
In function createNewInstance()
[Node2D:2385]
[Node2D:2385]
In function createNewInstance()
[Node2D:2406]
[Node2D:2406]
In function createNewInstance()
[Node2D:2427]
[Node2D:2427]
In function createNewInstance()
[Node2D:2448]
[Node2D:2448]

There should only be one call to createNewInstance(). I really don’t know what’s going on.

queue_free() does free() at the end of current frame.
It’s expected to be able to get reference after queue_free() within the current frame.

so, this codes…

print(instance)
instance.queue_free()
print(instance)

prints this

[Node2D:983]
[Node2D:983]

This is normal and expected.
nothing is wrong here.

I guess memory leaks somewhere else.

volzhs | 2018-04-10 15:29

try to find something is instanced but not added.

volzhs | 2018-04-10 15:37

Yes, I thought it was fine that print(instance) on the second time was printing the node. What I’m most concerned about is, why when adding the second (or sometimes later) instance suddenly the createNewInstance() function is being called so many times.

maou | 2018-04-10 15:51

maybe onSignal() is called so many times?
try to print something in onSignal() function or use breakpoint.

volzhs | 2018-04-10 16:38

Use call_deferred for add_child in _ready() function. SceneTree is locked during _ready() calls.

hilfazer | 2018-04-10 18:22