Hi.
This is my first post here. Sorry if am not doing it right.

How can I get updates from a static variable that gets changed/updated?
I know about "autoloads" and signals, but is it possible to check for/get updates without these methods?

I've done a simple example, three scenes with each script.
The scenes are: manager, button and label, where button and label is children of manager.

The manager shares a static variable between button and label.

class_name Manager

static var game_state : String = 'Play'

The button changes the "game_state" when its clicked

func _ready() -> void:
	if self:
		self.button_down.connect(change_game_state)

func change_game_state() -> void:
	var new_state = ['Exit', 'Pause', 'Play'][randi_range(0, 2)]

	Manager.game_state = new_state

And here is the problem! How can I make that when the static variable (game_state) is changed, that it also changes the label?
I thought it was possible to update the label with setters, but I just cant get it to work.
Label code:

var game_state : String = Manager.game_state :
	set = set_game_state

func set_game_state(value: String) -> void:
	if self:
		self.text = value

I would really appreciate any help I can get.
Thanks in advance.

  • systemerror replied to this.
  • 850815h I am not sure, if I understand your answer correctly, but what I get is, that you want the coupling to be as loose as possible. That is exactly what signals are made for. So your way to go is:

    • Let the button emit a signal, when it is clicked.
    • Let your manager react to this signal by updating its game_state, maybe use a setter.
    • In this setter (or any other function that updates the game_state), emit another signal game_state_changed.
    • Let your label react to this signal by updating its text.

    (Obviously, at same time (runtime or compile time), the manager needs to have a reference to the button as well as the label to the manager.)

    Side note:

    • As the game_state belongs to the manager, it does not seem to be appropriate to have it set by the button.
    • Making the game_state a static variable would only make sense, if a – hypothetical second manager – should share the same game_state. I do not know your use case, but this sounds odd to me.

    It is common to not have a child store a reference to an ancestor node, i.e. your button should not know about your manager. Instead, move your method change_game_state() to the manager and connect this method to the button's button_down signal.

    The parent may have and use a reference to a child, so in your manager, just add $label.text = game_state.

    If you still want to keep set_game_state() in your button class for some reason, you could create a signal in your manager class that is called, everytime Manager.game_state is changed. Then, connect a method of your label to this signal.

    P.S.: https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_styleguide.html#naming-conventions advises to use UpperCaseNodeNames.)

      850815h
      why not check in in _process (you need for example an extra variable where you remember old state):
      # Called every frame. 'delta' is the elapsed time since the previous frame.
      func _process(delta: float) -> void:
      if game_state != game_state_old:
      print("game_state changed")
      label.text = "changed"
      game_state_old = game_state

        Dodo_87

        Thank you for your answers!

        Absolutely right. My wrong there. Didn't think about it now when just trying to fix this "small" issue.

        It is common to not have a child store a reference to an ancestor node, i.e. your button should not know about your manager. Instead, move your method change_game_state() to the manager and connect this method to the button's button_down signal.

        Yes, this will work, but again, am trying to find a method without the "must" of having access to other nodes for them to work.
        I know i've made the manager-node parent of button and label, but what if the manager was not a parent?

        The parent may have and use a reference to a child, so in your manager, just add $label.text = game_state.

        As i've mentioned before, I would like to use other methods than signals or autoloads.
        Is it really not possible without signals/autoloads in Godot 4.X?
        Am a beginner when it comes to GDScript, but from what i've seen since 4.X the static variables is a game changer and should do exacly what I want, or am I wrong here?

        If you still want to keep set_game_state() in your button class for some reason, you could create a signal in your manager class that is called, everytime Manager.game_state is changed. Then, connect a method of your label to this signal.

        Got it! Thanks!

          systemerror

          Thank you for your answer!

          Yes, I've tried that and thats exacly what I want it to do, to automatically update itself, but here comes the problem with this method... It's asking for the changes every frame and I don't think thats a good idea. I just need the changes when they update.

          why not check in in _process (you need for example an extra variable where you remember old state):

          850815h I am not sure, if I understand your answer correctly, but what I get is, that you want the coupling to be as loose as possible. That is exactly what signals are made for. So your way to go is:

          • Let the button emit a signal, when it is clicked.
          • Let your manager react to this signal by updating its game_state, maybe use a setter.
          • In this setter (or any other function that updates the game_state), emit another signal game_state_changed.
          • Let your label react to this signal by updating its text.

          (Obviously, at same time (runtime or compile time), the manager needs to have a reference to the button as well as the label to the manager.)

          Side note:

          • As the game_state belongs to the manager, it does not seem to be appropriate to have it set by the button.
          • Making the game_state a static variable would only make sense, if a – hypothetical second manager – should share the same game_state. I do not know your use case, but this sounds odd to me.

            Dodo_87

            Sorry if I was unclear, what I'm trying to accomplish is to get updates other than signals, but I guess that's what signals are for. Thank you for your reply.

            I am not sure, if I understand your answer correctly

            Thanks for the tip

            Side note:...