Godot Getter And Setter

introduction

Godot getter and setter are really useful. Here are the things that I use them for.

clamping

This is pretty self-explainary - A value might have a minimum or maximum values and it would become really tedious to check every time you set the value. In Godot, you can do something like this:

const MAX_HEALTH := 100
var health := 100 :
    set(v):
        health = clamp(v, 0, MAX_HEALTH)

serial number

Sometimes, you might want something that would never repeat. In my case, this is used when syncing nodes between clients in a multiplayer game.

const MONSTER = preload("res://monster.tscn")

var serial_number := -1 :
    get():
        serial_number += 1
        return serial_number

# somewhere else in the code
@rpc("authority", "call_local", "reliable")
func spawn_monster(n:String):
    var monster := MONSTER.instantiate()
    monster.name = n
    # other stuff to initialize the monster such as its position or health
    add_child(monster)

func _on_timer_timeout() -> void:
    var n := "monster_%d" % serial_number
    spawn_monster.rpc(n)

warning

Usually, we should follow “the principle of least surprise”. This use case can be surprising to people who aren’t familiar with the codebase (or yourself after 6 months). Thus, perhaps this is better done using a function:

var serial_number := -1

func get_next_serial_number() -> int:
    serial_number += 1
    return serial_number

The code may look the same but it’s way less surprising than using the variable directly.

sync UI elements

Sometimes, you want a particular UI element to always represent a particular variable in the game such as player health, player mana, etc.

@onready var gold_label: Label = $"GoldLabel"

var gold := 0 :
    set(v):
        gold = v
        gold_label.text = "gold:%d" % v

exported variable

Note that, however, if the variable is exported and you set a value there, the setter would be called before the node is ready which might cause problem. In that case, just await for the ready signal:

@onready var gold_label: Label = $GoldLabel

var is_ready := false

@export var gold := 0 :
    set(v):
        if !is_ready:
            await ready
        gold = v
        gold_label.text = "gold:%d" % v

func _ready() -> void:
    is_ready = true
Written on January 18, 2025