I have a node (Player) referencing a custom resource, at a point in the game the node dies and transitions to a game over screen, on this screen there is nothing referenced to the custom resource and only the game over scene exists at this point.
You don’t free the player (if you don’t want to).
You must reset the resource variable.
class_name Player
@export var my_custom_resource:PlayerData
var my_int:int
var my_string:String
var my_float:float
func _ready()->void:
init_values()
func init_values()->void:
my_int = my_custom_resource.some_int
my_string = my_custom_resource.some_string
my_float = my_custom_resource.some_float
func restart_me()->void: # call this or just call init_values() when you restart
init_values()
I think this is the problem. If you change the value in the resource, it will load with the last value assigned to it.
Let’s say you have a Stats resource and it has a health variable. If you decrease the health value in the resource to 5, it will load with 5 when you call it again.
Usually we declare a variable in the object that uses the resource, then you change the values in the object variable, not in the resource. In the previous example, you would assign the health value from the resource to the health variable in the player. Whenever the player health changes, you change the variable from the player, not the resource.
Resources are basically “data storage”. We often use it to save stats, game settings, saves, etc. You don’t change it unless this is the intended behavior (you want to level up the character, update the game settings, save the game with the last info, etc).
Hmm, this is interesting: since resources are ref-counted, they should be freed when no reference is set. Even the documentation says
When a Resource is no longer in use, it will automatically free itself. Since, in most cases, Resources are contained in Nodes, when you free a node, the engine frees all the resources it owns as well if no other node uses them. Resources — Godot Engine (stable) documentation in English
So I played around with it and had the same experience as @Fryker. That is, freeing the parent does not free the resource.
However, this is only the case when setting a resource via an exported property or preloading it. In this case there seems there is always a reference to it, independent of the owning node being in the tree. The reason for this is that it is loaded when the when the owner script is parsed. You can check that by looking when the _init function of the resource is called. So as long as there is a reference to the owner scene/script, there will be a reference to the resource.
In any case, if you want the resource to be initialized and freed with the node, you can load the resource via the script (load not preload). In this case freeing the owner frees the resource (if it’s the only one holding a reference to it).
An alternative is to set the resource Local to Scene, then it is duplicated for every Player and freed with it. But this might not be what you want.
Thanks to you I found the problem, the player controller node loads a reference to the Player when starting the game
const PLAYER := preload('res://game/actors/player/player.tscn')
This causes the resource to be created, I guess, and since the player keeps a reference to the resource, is the resource always kept in memory? Even if the player node is not in the scene, since the player’s scene reference is always loaded in memory.
Oh yes, I forgot about preloading (I’m using C# where this is not possible). When preloading the scene is loaded when the script is parsed (similar to when set via @export).
As I understand it, the ‘problem’ is not preloading the player scene, but preloading the resource. You can preload the player scene. As long as you do not preload the resource (or set it Local to Scene when exported), then when freeing the player instance, the resource is also freed.
I think I misunderstood your question - my bad. I thought that your problem is that the resource is not freed when the player is freed. But you actually want to reset the resource on the same player instance - right?
In this case you could either do it like @sancho2 suggests or you use duplicate to duplicate the resource every time you want to reset it (this is basically what Local to Scene does when the scene is instantiated).
No, no, no, you understood my problem completely, it’s my fault for not expressing myself correctly and not understanding the suggestion, setting the resource to local to scene causes it to be deleted when freeing the player, which is what I was looking for, thank you very much, in your opinion is it better to preload the player or load it when I’m going to add it to the scene.
I would preload your player scene. This way it is loaded in the beginning and will not impact performance when the owning scene is instantiated the first time.