Why can I access a constant from another class but not a variable

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

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 :slight_smile:

:bust_in_silhouette: Reply From: timothybrentwood

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. Singletons (Autoload) — Godot Engine (stable) documentation in English

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):

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. :slight_smile:

Halflove | 2021-06-13 21:47