I have a class called Enemy, and a Resource called EnemyStats. I create a new enemy inheriting from the enemy class, and a new resource called test_stats, assign that to my enemy's export variable for the stats.

The Enemy clas script:

class_name Enemy
extends Node2D

@export var stats :EnemyStats

the new enemy's script:

extends Enemy

func _ready() -> void:
	print(stats)

This works fine, the enemy can access the stats correctly. I can change the values of the test_stats's max_health in the editor for example and that prints correctly too, all is well.

But if a setter function is assigned to the stats variable int he enemy class, neither the mother class script nor the daughter enemy script can access the stats resource anymore. It always prints as null:

class_name Enemy
extends Node2D

@export var stats :EnemyStats : set = set_enemy_stats

func set_enemy_stats(updated_stats):
	pass

Mind you, I didn't come up with the idea of a setter function, i'm following a YouTube tutorial and been experimenting a little with the provided code. Now i've run into this issue and would like to understand what exactly is happening here. What is causing the stats resource to suddenly become null? Do resources just not work right with setter functions?

  • Well, i played around some more and i'm not entirely sure what happened... but it just works now? The setter sets the stats correctly and doesn't make them vanish.

    My best guess is that i mixed up the order of stats & updated_stats.
    So like this:

    func set_enemy_stats(updated_stats):
    	updated_stats = stats

    It should have been this:

    func set_enemy_stats(updated_stats):
    	stats = updated_stats

    But honestly, i have no idea what i'm doing differently. I played around with this for hours yesterday, not being able to make it work. This is just weird.

Your setter function doesn't set the variable. Therefore it can not be changed and will always be null.

    Zini I don't understand what you mean. I thought a setter function gets activated on it own when the variable it is attached to changes. Where did i do wrong? Could someone correct the code here so i know what i need to change?

    • Zini replied to this.

      Squiddy

      I thought a setter function gets activated on it own when the variable it is attached to changes. Where did i do wrong?

      Yes, your setter function does get called. But it doesn't do anything (the body of the function consists only of a pass). It is supposed to set the variable (and probably do some other stuff that is the reason you want a setter in the first place). Setting the variable is not something it does automatically. You need to assign something to stats in the function or stats stays null.

        Zini Okay i do understand that. I left the setter function empty on purpose, because if i put anything into the function, it crashes. Because it cannot access the stats, because the stats are null. That's the whole problem, not the setter being empty but the setter not able to access the stats at all! What i don't understand is what happens to my stats resource, why it turns into null along the way...

        Well, i played around some more and i'm not entirely sure what happened... but it just works now? The setter sets the stats correctly and doesn't make them vanish.

        My best guess is that i mixed up the order of stats & updated_stats.
        So like this:

        func set_enemy_stats(updated_stats):
        	updated_stats = stats

        It should have been this:

        func set_enemy_stats(updated_stats):
        	stats = updated_stats

        But honestly, i have no idea what i'm doing differently. I played around with this for hours yesterday, not being able to make it work. This is just weird.

        Okay. One more try to clarify it.

        When you write x = 1 GDScript will assign the value (1) to the variable (x). Unless x has a setter. In this case this behavior is suppressed and instead the setter function is executed with the value passed in as an argument (updated_stats in your case).

        So, yes. The problem was that the setter was empty (or had defective code in it). Any setter that does not assign to its variable is broken and will cause problems. The first version you posted is plain wrong. The second version is correct, even though it is useless. Your setter does exactly what would happen by default if the variable did not have a setter.

          Zini
          can maybe someone shed light what is the advantage of using setter functions? if you really need to check if value is valid or do anything with it before setting you can do that before setting it outside the setter function? or am i missing something?