Variables, Constants, Enums & Static Typing
Default values: int → 0, float → 0.0, bool → false, String → "", Vector2 → (0, 0), objects → null, Array → [].
6.1 Declaring variables
Dynamic (Variant); any type can be assigned later var x: int = 5 Static type hint
Static, type inferred from the initializer Static, default value (0 for int)
Default values: int → 0, float → 0.0, bool → false, String → "", Vector2 → (0, 0), objects → null, Array → [].
var health = 100 # dynamic: can later hold any type
var player_name: String = "Ada" # explicit type hint
var speed := 250.0 # inferred type (float) — static, cannot change type
var target: Node2D # typed, default null
var items: Array[String] = [] # typed array6.2 Scope
Member variables (declared at the top level of a script) belong to the instance.
Local variables live inside a function or block.
Static variables (4.1+) belong to the class and are shared by all instances:
class_name Enemy
extends CharacterBody2D
static var alive_count := 0
func _ready() -> void:
Enemy.alive_count += 1
func _exit_tree() -> void:
Enemy.alive_count -= 16.3 Constants
Constants must be known at compile time. Arrays and dictionaries declared const are read-only (Godot 4).
const MAX_SPEED := 600.0
const GRAVITY: float = 980.0
const DIRECTIONS := [Vector2.UP, Vector2.DOWN, Vector2.LEFT, Vector2.RIGHT]
const BulletScene := preload("res://bullet.tscn") # preload is a constant expression6.4 Enums
A named enum is a constant Dictionary mapping names to ints, and also a type usable in type hints and @export.
Enum values are ints; cast with state = State.JUMP or state = 2 as State.
Enums declared with class_name are accessible elsewhere: Player.State.RUN.
enum { NORTH, EAST, SOUTH, WEST } # unnamed: creates constants NORTH=0, EAST=1 ...
enum State { IDLE, RUN, JUMP, FALL } # named enum
enum Element { FIRE = 1, WATER = 2, EARTH = 4, AIR = 8 }
var state: State = State.IDLE
func _ready() -> void:
print(State.RUN) # 1
print(State.keys()) # ["IDLE", "RUN", "JUMP", "FALL"]
print(State.find_key(state)) # "IDLE"
print(State.size()) # 4
for s in State.values():
print(s)6.5 Static typing in depth
Static typing gives you:
Errors at compile time instead of runtime crashes.
Better autocompletion.
Faster execution (typed instructions; no runtime type checks for many operations).
Error if a non-int is assigned (ints convert to float automatically for float) var a:= 1.5 Type fixed to float func f() -> int: -> void for none
Objects: returns null on failure; built-ins: converts or errors Works for built-ins, classes, scripts
Array[int], Dictionary[String, int] (4.4+) Elements checked on insert
The editor marks type-safe lines with a green line number. In *Project Settings → Debug → GDScript* you can turn warnings like UNTYPED_DECLARATION, UNSAFE_PROPERTY_ACCESS, and UNSAFE_METHOD_ACCESS into errors to enforce fully typed code.
Godot 3 note: static typing arrived in 3.1; := and typed arrays exist in 4.x only in their current form (3.x had no typed arrays).
func heal(amount: int) -> void:
health = min(health + amount, max_health)
func get_direction() -> Vector2:
return Input.get_vector("left", "right", "up", "down")
var enemy := $Enemy as CharacterBody2D # cast; null if the node is not that type
if body is Enemy: # type check (works with class_name)
(body as Enemy).take_damage(10)6.6 null and Variant
Variant is the universal type that can hold any value. Untyped variables are Variants. null is the "no value" value; accessing a member on null is a runtime error:
is_instance_valid(obj) also detects objects that were freed (a freed object is not automatically null).
var target: Node2D = null
if target != null and is_instance_valid(target):
look_at(target.global_position)