• Godot Help
  • How can get a variable from a free-standing script unattached to a node?

The subject pretty much defines the problem but here is WAY more detail, lol.
I'm locked into a certain structure at this point and find myself in a quandary.
I have isolated scripts sitting in sub-folders and based on a variable in those scripts I would choose to load one of two kinds of scenes (2D or 3D). That script will end up getting attached to a node in that scene.

I've thought about dynamically creating a dummy node, attach the script located in the folder I want to reference, get the variable, then toss the dummy node, load the main scene I need, and attach the script to that.
I wouldn't need to do that klunky process if I can just read from the script directly. I've seen the idea of preloading a script as a global resource but there is nothing global about these scripts, in fact it's the opposite.

    That won't work for me but thanks. I think some of my other scripts could work as globals.
    Can I just import a script inside another script?

    Shadowphile I've thought about dynamically creating a dummy node, attach the script located in the folder I want to reference, get the variable, then toss the dummy node, load the main scene I need, and attach the script to that.

    If I understand your problem correctly then yes, I think that is what you need to do. Create a temporary node, attach your deciding script, check the variable and then remove the temporary node.

    Might I ask why you have a setup like this? What are you trying to do?

    Shadowphile There's no such thing as "variables inside scripts". Every script is a class and everything you declare in a script is a property of an object of that class. You need to instantiate an object to actually "materialize" its properties. Unless... you declare a property static. This makes it class-wide and not associated with any object. Now you can access it from other scripts only via class name, without an object instance.

    class_name MyClass extends RefCounted
    static var some_data = 1
    print(MyClass.some_data) 
    • Zini replied to this.

      xyz Isn't the syntax static var some_data = 1?

      Also, we probably should point out that static variables are a recent addition. Godot 4.1, I believe? Not available in 4.0 or 3.5.

      • xyz replied to this.

        Zini Yes. Corrected. Thanks for spotting the mistake.
        I thought static vars were added in 4.0, but I'm not sure. Might be 4.1 as well. They are definitely not in 3.x, although you can have static methods in 3.x.

        It's worth noting that static vars make the "old way" of handling global data via autoloaded singleton nodes pretty much obsolete.

        I read about making classes to make variables accessible but my head starts to spin when I think of declaring classes.
        In another thread I did find a way to build/instantiate in a sequence that addresses my need.
        Whether this will all be exportable is another issue altogether, sigh.

        • xyz replied to this.

          Shadowphile If you create a script - you have made a class. There's no way around it. It's far from head spinning stuff 🙂

          Important to note that any script you add to Autoload will create a Node to attach it to when you run, then child that Node to the root. There's no way to get around Nodes with Autoload.

          In 4 you can have a class with static variables that doesn't inherit from Node (it will still inherit from Object *RefCounted (Thanks xyz)), name it, and then access its static/const members from anywhere.

          class_name StaticStuff
          
          static var some_static_var := 1
          const some_const_var := "I'm a const!"
          
          enum DangerousTallBirds {
          	EMU,
          	OSTRICH,
          	CASSOWARY,
          	RHEA
          }
          
          enum {
          	YOU_CAN_ACCESS_THESE_TOO
          }
          
          static func static_func() -> void:
          	print("I have been called.")
          
          func non_static_func() -> void:
          	push_error("How did you get here? Leave at once!")

          accessed like so:

          extends Node
          
          func _ready() -> void:
          	print(StaticStuff.DangerousTallBirds)
          	print(StaticStuff.some_static_var)
          	StaticStuff.some_static_var = 300
          	print(StaticStuff.some_static_var)
          	print(StaticStuff.some_const_var)
          	print(StaticStuff.YOU_CAN_ACCESS_THESE_TOO)
          	StaticStuff.static_func()
          	#StaticStuff.non_static_func()
          	#^Error: Cannot call non-static function "non_static_func()" on the class "StaticStuff" directly. Make an instance instead.
          	var instance := StaticStuff.new()
          	instance.non_static_func() #Can call off of instance
          • xyz replied to this.

            award For a fully static class that won't ever be instantiated, it doesn't really matter what it inherits.

            Btw if you don't specify class' parent, its inheritance will default to RefCounted, not Object.