+2 votes

I kind of wondered how do you write a static variable if it is possible in GDScript. Hope to find answers!

in Engine by (63 points)

3 Answers

–11 votes

Not sure what you are calling static variable but GDScript has support for constants through the const keyword.

by (1,041 points)

A static variable is like a static function -- it's available without an object instance, addressed through the class.
So, just like you can call MyClass.function() you should be able to address class variables using MyClass.variable
A constant is something totally different.
This question is the top Google result for "godot static variable" and doesn't answer the question, so poking it here, because I have the same question ...

The answer is that "there are no static variables, because those are effectively global, and would be less thread and memory safe than the current constructs."
The least-bad work-around I've found is to hang some custom node of known name off of the scene root, and put members on that node. Which in turn requires the scene to be available.

My answer might not be quite clear. I know what is a static variable, but I don't see why you would use static variable in Godot, I don't see any good reason that are not covered by a constant.

I just gave you one: Count how many times each particular kind of event happens, or each particular function is called. Not per class instance, but overall.

Not sure how this example is relevant for game development in GDScript, but that could be easily done with a singleton.

OK, maybe I need to look into Singletons then...

Hey Jon Watte, I'm liking your thinking... I was just wondering today how to implement static variables in godot. I'm coming from a C# background and I'm also missing private variables. In working on my first godot game using just Gdscript. When it's finished I will redo the whole thing in C# just to see how the experience goes. I the meantime, I will defo use your idea re the static vars.

Come on, this isn't Stack Overflow. We know it is not always good practice, so just try and answer if you can. Hope you have a good one though.

+2 votes

Check out the section on singletons in the documentation:

https://docs.godotengine.org/en/latest/getting_started/step_by_step/singletons_autoload.html

"Godot’s scene system, while powerful and flexible, has a drawback: there is no method for storing information (e.g. a player’s score or inventory) that is needed by more than one scene."

by (18 points)
+2 votes

I agree that it would be convenient to have static variables. These should be common to the class, not the object, just like constants. But contrary to constants, it should be possible to modify them.

I suggest that a var declaration could be prescribed with the static key word:

const MYCONST # shared with all objects of this class, non-modifiable (existing)
static var my
static_var # shared with all objects of this class, modifiable (suggested)

However, as a workaround, it's possible to use the metadata for the gdscript of the class. Metadata is a dictionary which every Object in Godot has. Since a GDScript is a Resource and a Resource inherits from Object, also the gdscript (the class itself) has a metadata dictionary as a member.

Here's an example from my game. I have a number of factions and each faction should start the game with 2 scout units each. I want the names of the scout units to be like "1st Scout", "2nd Scout", "3rd Scout", "4th Scout", where 1st and 2nd belongs to the first faction, 3rd and 4th belongs to the second faction, and so on. The order number of the scout unit should reflect the total number of units having been created so far of the scout class.

To achieve this, I put a counter variable in the metadata of the Scout gdscript.

I put the scout generation in the Faction script and it looks like this:

const SCOUT_TEMPLATE = preload("res://squad/Scout.tscn")

func setup(game):
    # create scouts
    for i in 2:
        var scout = SCOUT_TEMPLATE.instance()
        var scout_class = scout.get_script()
        var counter = scout_class.get_meta("counter")
        counter += 1
        scout.number = counter  
        scout.name = scout.get_unit_name("Scout")       
        scout_class.set_meta("counter", counter)
        scout.faction = self
        game.squad_node.add_child(scout)
    pass

func _ready():
    var scout_class = load("res://squad/Scout.gd")
    if not scout_class.has_meta("counter"):
        scout_class.set_meta("counter", 0)  
    pass

For each scout unit created, the class counter is fetched from the metadata of the class, it is increased by 1, and then saved back into the metadata.

The getunitname("Scout") function generates the name, like "1st Scout".

by (18 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.