Variables Within "_pressed" Function Won't Update

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

Using GDscript in Godot 4 (v4.0.2).

If you assign a variable to the top of a script (outside of any functions), then try to access and change that value inside of a “func _pressed” statement on a button press, Godot makes a copy of that variable and only makes changes to the copy within the function “_pressed”, and won’t update the variable outside of this function.

Say you have two buttons linked to “_pressed” each button while pressed will maintain its own copy of that variable.

If you create and use a Globals variable the behavior works as expected without producing copies.

Example code:

var myNumber = 1

func _pressed(): # Runs every time you press a button the script is linked to.
myNumber += 1
print (myNumber)

printing myNumber will give you results as expected until you click another different button, then you start to see copies appearing.

If you print “myNumber” outside of the scope of _pressed, say every frame on “_process”, you will see that myNumber is still 1 and was never iterated or updated.

This tells me that Godot is making a copy of “myNumber” per button pressed and making changes to that copy per specific button.

Does anybody know why exactly this happens or how to fix it aside from using Globals?

:bust_in_silhouette: Reply From: jgodfrey

If I understand what you’re saying, that doesn’t sound right. And, based on a quick test here, that’s not what I see. I set up a script-level variable, incremented it within a match statement based on a button press (and printed it each time to verify its value).

Then, I printed the value from a second button press (and a second pressed even handler) and I get the correct (properly incremented) value.

That’s how I’d expect this to work, and how it appears to work for me.

Can you show some simple code that replicates the issue?

If I had to guess, I’d say that you inadvertently created a local variable with the same name as your global variable somewhere.

There are no redeclarations anywhere in my script (locally or otherwise). I have however figured out what is wrong on a surface level. It had nothing to do with the match statement, as if/else had the same issue.

The issue is that the function I’m running “func _pressed()” which is connected to multiple buttons is actually making instances of the variable then only making changes to those instances.

I never made any redeclarations, and perhaps this is intended behavior that I just don’t understand. I really don’t see why the built-in function “_pressed()” would not allow variable data above its scope to be updated and instead automatically produce its own copies. I have tested with several other variables and indeed it is making copies.

I updated my question to better reflect my new understanding of the problem.

Thanks for the answer!

Krotack | 2023-05-09 01:23

This still doesn’t make sense to me. I’ve changed my test code so that I have 2 buttons, each wired to the same pressed event handler. That handler simply increments a script-level count variable and displays its value in an on-screen label. So, pressing either button increments the variable via the same handler function.

Additionally, I’m printing the current value of count to the console in each frame via _process().

As I’d expect, I only see the latest value of of count shown in the label and the continual console output, and pressing either button increments the value by 1.

jgodfrey | 2023-05-09 01:38

Okay I just tested with a brand new scene and the issue persists, and I’ll explain (with code) what is wrong.

So I setup a blank brand new scene. I then create two buttons.
I then add a script, the same script, to both buttons.

I then setup “_pressed()” by adding signal nodes to their respective self scripts, the way you normally do.

Then I write this code:

extends Node
var myNumber = 1

func _on_pressed():
myNumber += 1

Every time you press one of the two buttons it increments, as it should, but there are several copies of “myNumber” being incremented.

Now click button 1 ten times, you will see print(myNumber) print 10.
However if you click button 2 once, you will see it jump back down to 2.

These two are not linked together, suggesting they are copies of the same data, despite both referencing the exact same variable.

I probably just don’t understand what is happening, but both buttons should just increment the data, button 1 and button 2 should produce the same information on press, but they differ depending on how many times I press each one.

Krotack | 2023-05-09 01:50

Imgur: The magic of the Internet

I added an image here as an example. Pressing button 1 a dozen or so times, then pressing button 2 a few times, look how the values aren’t synced. Again, I’m sure it’s just something I don’t understand with how the function operates.

Krotack | 2023-05-09 02:05

Wait - so each button has its own instance of the script? In that case, I guess I’d expect the variables within each script to be independent of one another - as you describe.

jgodfrey | 2023-05-09 02:22

That makes perfect sense, it kind of flew over my head for some reason as I am so new to Godot and adding scripts to objects like this. That would explain why a global variable fixes this issue. Signaling to one script makes way more sense, so I’ll do that in the future.


Krotack | 2023-05-09 02:30

A typical configuration would be to place the script on the root of the scene containing the (in your case) buttons. Then, each button can be connected to the same pressed event handler, which would live in the SINGLE script at the root of the scene. And, it doesn’t have to be stored on the root. But, generally, it’d be some common ancestor of the buttons…

jgodfrey | 2023-05-09 13:28