Why are static variables/const not a thing in gdscript ?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Moros

I was wondering why it isn’t possible to define a static variable or constant in gdscript, I guess it is like that by design but I don’t get it at all

:bust_in_silhouette: Reply From: magicalogic

A constant can be defined using const key word, only a static variable can’t be daclared, no idea why.

:bust_in_silhouette: Reply From: MagnusS

If you mean global variables, you can use singletons to define variables that can be accessed from anywhere in your program.

No he’s not talking about globals most likely he’s a C/C++/C# programmer

Those languages you can keep var in memory like this

func setup():
    static bool runOnce = true:
    if runOnce:
        runOnce = false
        print("setting up")

No matter how many times you call the func setup() “setting up” will only be called once

Honestly this is only necessary in low level languages where you have to do memory management yourself

Wakatta | 2021-05-08 14:40

I had another exemple in mind :
I was just working on a custom camera and I wanted to implement animation for the camera movement, I was thinking of using the Tween class to help me move the camera, the problem is I wanted to have an exported parameter inside my CustomCamera class to let the user of this class select the type of transition they want.
Something like that would do the trick

exported (Tween.TransitionType) transition_type:int = Tween.TransitionType.TRANS_LINEAR

But I can’t because the enum TransitionType inside the Tween class can’t be set as static, to access the enumeration I have to instance an object first (a thing I can’t do when exporting variable)

But yes I mostly have experience with C/C++/C#/Java languages so removing the possibility for me to declare parameters as static is tricky to me, I have to rethink entirely how to manage variables

Moros | 2021-05-08 18:21

I believe the way Godot sets up enums are like this
enum {TYPE1, TYPE2, TYPE3} so there exists no TransitionType var as they are added directly to the node

The quickest approach I can think of for your dilemma is to define your own transitions enum

enum TRANSITIONS { LINEAR, CIRC, BACK}
export(TRANSITIONS) var transition = TRANSITIONS.BACK

Wakatta | 2021-05-08 21:14

:bust_in_silhouette: Reply From: Mario

As others have mentioned, Godot indeed knows the const keyword, which will work pretty much the way you (probably) expect it to do.

For static it’s different, because even in C/C++ the meaning changes based on the context it’s used in. It may hide a symbol from other translation units, it might mark a local variable global or “static” to all calls of a function, and it might mark a class member shared between all instances. All these things are possible in Godot, too, but there’s no specific keyword to it and you might have to add some more “glue” to get the intended behavior.

##One-time initialization/lockout
I guess this is most likely what you were looking for.

In general, I’d try to avoid this approach. If you have to fill an array or something once, try doing so in _ready(). If you really want to do it (e.g. it’s heavy and you don’t want to do it all the time), just create an extra variable holding the status. This is something C/C++ compilers will do in background, too. It’s actually extra overhead many forget whenever they throw in static somewhere.

var something_init: bool = false
var something: int = 0
func some_method() -> void:
    if not something_init:
        something_init = true
        # initialize something one time here
        something = get_starting_value()
    # do something else
    something += 1

##Hide symbol from other translation units
This doesn’t really apply to Godot, since (so far) there’s no way to directly refer to stuff from other code files (or use headers or similar).

##Global variables shared between class instances
This is again something I’d try to avoid, but if you really have to, you can do so by moving your “static” variable to a global singleton.

Singleton (statics.gd instantiated as Statics)

var myClassCounter: int = 0

Class

func _ready():
    Statics.myClassCounter += 1
:bust_in_silhouette: Reply From: Levi Lindsey

Here’s another work-around for static variable in GDScript, which hasn’t been mentioned yet.

  1. Define a const Dictionary variable on your class.
  2. Store and access your static variables as properties on that Dictionary.

This works because the const Dictionary instance is shared between instances of the class. Even though the Dictionary is const and can’t be re-assigned, it is still “mutable”, so you can change its properties as much as you want.

Here’s an example:

class_name Main
extends Node


func _ready() -> void:
    var a := MyClass.new()
    var b := MyClass.new()
    
    a.STATIC_VARIABLES.is_my_flag_enabled = true
    
    assert(b.STATIC_VARIABLES.is_my_flag_enabled)


class MyClass extends Reference:

    const STATIC_VARIABLES := {
        is_my_flag_enabled = false,
    }