0 votes

Suppose I have a bunch of "enemy"- nodes with individual sprites.
Now during level design I'd like to have a single "global" variable "scale" to affect all the sprite scales at the same time.

I've created a Node "GlobalVars". Then I've added a script:

tool
extends Node
export var myscale=1.0

The Sprites also have a script attached, which looks something like

tool
extends Sprite

var rscale =1.0 setget myset,myget #dunno if I need to use setter or getter
var cntrl   #reference to my Node GlobalVars

func _ready():
    cntrl=get_node("/root/Main/GlobalVars")
    rscale=cntrl.myscale    
    self.scale=Vector2(rscale,rscale)

func myset(nuval):
    cntrl=get_node("/root/Main/GlobalVars")
    rscale=cntrl.myscale    
    self.scale=Vector2(rscale,rscale)


func myget():
    cntrl=get_node("/root/Main/GlobalVars")
    rscale=cntrl.myscale
    self.scale=Vector2(rscale,rscale)

I've reloaded the scene and immediately Godot tells me that it wasn't able to find the Node called "GlobalVars"... However, godot runs scene is runnable and it also uses the proper scaling from the GlobalVars-Node, i.e. the Nodepath is all right..

What am I doing wrong ?
Is there a better way to accomplish what I'm trying to do? (I started to play around with Godot 2 days ago...)
I feel like there should be a cleaner way

Any suggestions?

best regards,
frankyboy.

asked Dec 21, 2019 in Engine by frankyboy (15 points)

1 Answer

0 votes
Best answer

It tells you GlobalVars is not found because you made your scripts run in the editor. A scene in the editor is a slightly different environment from a running game, in particular when it comes to absolute paths:

cntrl=get_node("/root/Main/GlobalVars")

This path won't work in the editor because /root will be the root of the editor itself.

  • You might want to consider using a relative path, or another way to reference the scale variable.

  • You might try using an autoload, which is the most commonly suggested, but I don't know if tool works on them in the editor.

Another way is to use a get_node_in_parents() pattern, so the first parent found having the scale script will be used. This is good if you want to keep your scale local to the children of the node:

static func get_node_in_parents(node, klass):
    while node != null:
        node = node.get_parent()
        if node != null and node is klass:
            return node
    return null

Get first parent node having the Globals.gd script on it:
get_node_in_parents(self, preload("Globals.gd")).myscale.

  • Yet another way would be to not use nodes, but a shared resource instead. Make your myscale script extend Resource, and attach it to a Resource object which you can save next to your scene. Then attach that resource to each node where you want to use the scale. This way, if you modify the resource, all nodes having it will be able to access it.

  • Or again another way is to put your scale script into a special group, and make other nodes access it using get_nodes_in_group("globalscale")[0].myscale.

answered Dec 21, 2019 by Zylann (26,157 points)
selected Dec 21, 2019 by frankyboy
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.