The place where random ideas get written down and lost in time.

2024-07-09 - Godot GDSCript Static Typing

Category DEV

GDSCript: https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/index.html

https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/static_typing.html

var damage = 10.5                                ⇒ no typing, this is essentially a Variant

var damage:= 10.5                                ⇒ inferred typing

var damage: float = 10.5                ⇒ explicit typing

For constants:

const MOVE_SPEED = 50.0                        ⇒ inferred (= and := are the same)

const MOVE_SPEED := 50.0                ⇒ inferred

const MOVE_SPEED: float = 50.0        ⇒ explicit

For functions:

func sum(a: float = 0.0, b: float = 0.0) -> float: …

func sum(a := 0.0, b := 0.0) -> float:

Which types to use:

https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/static_typing.html#what-can-be-a-type-hint

Types can be:

  • Variant, void (only function return, see below)
  • Built-in types, global classes, inner classes (gdscript has inner classes?!)
  • Native classes, enums (gdscript has enums?!)
  • Constants that are preloaded as class types (see below)

func blah() -> Variant: …         ⇒ forces the function to return something

func blah() -> void: …                 ⇒ forces the function to not return a value

A note about class_name:

  • When used, it “registers” the class name globally, and it can be used anywhere.
  • Without it, one can “locally” preload a gd into a constant to create a class name:

        const Rifle = preload("res://player/weapons/rifle.gd")

                var rifle: Rifle

load(“some.gd”) happens at runtime and can go only into a “var”.

preload(“some.gd”) happens at compile time (reference) and goes into a “const”.

Array types:

The syntax is “ var: Array[type]”:

var scores: Array[int] = [10, 20, 30]

var vehicles: Array[Node] = [$Car, $Plane]

var items: Array[Item] = [Item.new()]

Used for for loops, but ignored in array methods and operators (array + array, or array[index]).

In Godot 4.2, an untyped array can be locally typed in a for loop:

        for name: String in names: …

Typed dictionaries are currently not supported.

Type casting and checking:

Example:

func _on_body_entered(body: PhysicsBody2D) -> void:

        var player := body as PlayerController        # ⇐ null if it cannot cast

        if not player:

                return

The type casting keyword is “as” : “instance as type”.

Warning ⇒ Use := to force the var to be typed -- apparently, it would not be overwise.

The destination var would be null if the type cannot be cast.

Warning ⇒ The silent null in case of non cast is allegedly a frequent source of bugs.

A safer way is thus to do an “is” check (like I was doing, because I didn’t know better anyway):

        if not (body is Type): … skip or pass

        var player: Type = body        # ⇐ this throws if it cannot cast

        etc

(I typically just write “if not body is Type” but I notice the example wraps that in parentheses??)

Inner Classes

Not related to type hinting, just types in general, GDScript does have inner classes:

https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_basics.html#doc-gdscript-basics-inner-classes

class_name SomeClass

class SomeInnerClass:

        var a = 5

        func someFunc(): …

func _init():

        var c = SomeInnerClass.new()

Question: are these static inner classes or are they bound to their parent class?

Class Constructor vs Static Constructor

An init constructor can call a parent base class:

class_name SomeClass

func _init(arg):

        super(“some value”, arg)

and have a static initializer:

static var my_static_var = 1

static func _static_init():

        my_static_var = 2

Typed Getters and Setters:

Example:

var seconds: int:

        get:

                return milliseconds / 1000

        set(value):

                milliseconds = value * 1000

Note the “: Type:” syntax.

If the getter/setters have functions, there’s an alternative syntax:

var my_prop:

        get = get_my_prop, set = set_my_prop

var my_prop: get = get_my_prop, set = set_my_prop

Lambda Functions:

Lambda functions are created inline as such:

        var myLambda1 = func (param1, …paramN):

                body

        var myLambda2 = func(): print(“something”)

or directly as arguments:

        someobject.connect( func(): print(“blah”) )

The type of a lambda is a Callable https://docs.godotengine.org/en/stable/classes/class_callable.html#callable 

Note that a Callable is also a type that can call any function by name:

        func something(arg1, arg2) : …

        var myCallable = Callable(self, “something”).

        myCallable.call(arg1, arg2)...


 Generated on 2025-01-18 by Rig4j 0.1-Exp-f2c0035