In some custom resources I have been using, some values were returning the default value I set in the _init() function of the custom resource despite me setting the value to something else.
This is an example resource where I set the custom_value to 5 by default in the _init() function. I then create and save a resource value_is_0.tres where I set the custom_value to 0.
class_name CustomResource
extends Resource
@export var custom_value: int
func _init(p_custom_value: int = 5):
custom_value = p_custom_value
However, when I load value_is_0.tres and print custom_value, it prints as the default value of 5.
func _ready() -> void:
var custom_resource: CustomResource = ResourceLoader.load("res://value_is_0.tres")
print(custom_resource.custom_value)
Question
So what I’ve figured out is that the inspector thinks the default value is 0 instead of 5, so when I set the value to 0, it just thinks I have set it to the default value and not necessarily 0. Then during runtime, it loads in the actual defaul value I set in _init(). This can be easily fixed by setting the default value in the @export var custom_value: int line like so:
class_name CustomResource
extends Resource
@export var custom_value: int = 5
func _init(p_custom_value: int = 5):
custom_value = p_custom_value
However, this creates the problem where I have to set the default value twice, which is simple here, but I’m worried about resources where I have several variables and eventually running into human error and setting the default values differently on accident. Is there a way to avoid this? Is this intended behavior and if it is, I feel like it should be documented somehow in the Resource page in the godot documentation.
Don’t override _init. Nodes and Resource types do a lot after _init, overriding init especially with arguments is almost always a bad idea. In this case @export is run after _init
If that’s the case, the docs are a little misleading. This is from the Resourcespage:
class_name BotStats
extends Resource
@export var health: int
@export var sub_resource: Resource
@export var strings: PackedStringArray
# Make sure that every parameter has a default value.
# Otherwise, there will be problems with creating and editing
# your resource via the inspector.
func _init(p_health = 0, p_sub_resource = null, p_strings = []):
health = p_health
sub_resource = p_sub_resource
strings = p_strings
Maybe I’m reading the docs incorrectly, but I am reading from the resource during _ready(). This issue does not occur if I set the custom_value to anything other than 0 in the inspector. If I set it to 1, it will print 1, its only when I set it to 0, that it prints the 5 that’s set as “default” in _init.
edit: Attached picture showing setting resource value to 1.
Non-@tool scripts aren’t fully loaded in the editor so your _init() assignment won’t run when you create a new Resource from it.
They are partially parsed to get some information like which variables are exported and their default value which is the value yo assign to the @export variable. You can see which default value does the variable have with Script.get_property_default_value()
So:
class_name CustomResource
extends Resource
@export var custom_value: int
Will have its default value set to 0 while
class_name CustomResource
extends Resource
@export var custom_value: int = 5
will have it set to 5.
This happens even if the script is a @tool script. Whatever value you set will be its default value. So if we convert the script to a @tool script:
@tool
class_name CustomResource
extends Resource
@export var custom_value: int
func _init(p_custom_value: int = 5):
custom_value = p_custom_value
custom_value default value will still be 0 but, because _init() is run, in the inspector it will show a 5 when you create the Resource. It will load the value you assign it to afterwards. The value will still reset to its default value 0 if you click on the reset button.
@tool
class_name CustomResource
extends Resource
@export var custom_value: int = 5
func _init(p_custom_value: int = 5):
custom_value = p_custom_value
If it has assigned a 5 then its default value will be 5 and when you create a Resource from it the value will be set to 5. The reset button will reset the value to 5.