0 votes

Hey there!

So I'm basically trying to change a variable in one script/class via another script. However, for some reason I can only access constants from the first class and not variables:

extends KinematicBody2D

class_name Player

var velocity = Vector2(0, 0)

const speed = 60
const decel = 0.3
const gravity = 19
const jumpForce = -230
var speedMod = 1.0

var canMove: bool = true
var currentState: String = "default"

Other script:

extends Area2D

class_name ChopOakTree

var canInteract = false
var chopped = false
var respawnTimer = 600
var timer = 0

# Sets tree status to chopped or grown depending on timer status
func adjustChoppedStatus(input: String):

    # chopped bool must be disabled when the tree is chopped so that
    # the player enter and exit events won't affect the displayed text
    # Change sprite animations and timer status dependant on input
    if(input == "start"):
        Player.currentState = "chop"
        Player.canMove = false
    elif(input == "chopped"):
        $AnimatedSprite.play("chopped")
        Player.currentState = "default"
        Player.canMove = true
        timer = respawnTimer
        chopped = true
    elif(input == "grown"):
        $AnimatedSprite.play("default")
        get_node("Node2D/UI/Label").text = ""
        chopped = false

(I shortened the scripts a little bit to only show the pertinent info)
So as you can see in the ChopOakTree class I'm trying to access the currentState and canMove variables from the Player class. However, it won't let me access or modify them, It returns with the error:

Invalid set index 'currentState' (on base: 'GDScript') with value of type 'String'.

I am really confused about this, why can I get the value of a constant from the Player class, but I can't get the value of a variable from the Player class?

Thanks in advance :)

Godot version 3.3.2
in Engine by (20 points)

1 Answer

+2 votes
Best answer

In your context Player is just a class, it's not an instance of a class. This is why you can access constant variables from it but not modify any behavior of it.

If you only intend to have one Player object, make it an auto-load singleton then you'll be able to modify the variables the way you have it coded. https://docs.godotengine.org/en/stable/getting_started/step_by_step/singletons_autoload.html

If you intend to have multiple Player objects, you'll need a reference to the particular Player object you want to modify. You'll probably want to use the body_entered signal of the Area2D to get a reference to a specific player. Generally speaking, you want to emit a signal and let the Player object do the work of adjusting its status. It makes code much easier to maintain.

As a side note, I would also suggest that you look into using enums instead of strings. They maintain the readability of strings but they aren't prone to misspelling and Godot will give you auto-completion on them.

enum CHOPPED_STATUS {START, CHOPPED, GROWN}
....
func adjustChoppedStatus(input: int):
...
    if(input == CHOPPED_STATUS.START):
by (2,832 points)
selected by

Thank you very much, I got it working now. Also, I'll definitely be using enums, just wanted to learn more about GDScript before I start cleaning up my code. :)

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.