Functions & Lifecycle Callbacks
Learn GDScript function syntax, return types, default parameters, and the built-in lifecycle callbacks Godot calls automatically.
Introduction
GDScript functions work much like functions in any language — but a special category of them, "lifecycle callbacks," are called automatically by the Godot engine itself at specific moments, without you ever calling them directly. Understanding those is central to writing any Godot script.
- How to declare functions, with return types and default parameter values.
- What _ready() is and when the engine calls it.
- The difference between _process() and _physics_process().
- How @onready variables tie into the node lifecycle.
Declaring Functions
func greet(name: String) -> String: return "Hello, " + name + "!"
print(greet("Isha"))Click Run to see what this code prints.
Return Types and Default Parameters
A -> Type annotation on a function declares its return type (optional, but recommended for clarity). Parameters can have default values, making them optional at the call site.
func take_damage(amount: int, is_critical: bool = false) -> int: var total := amount if is_critical: total *= 2 return total
print(take_damage(10)) # 10print(take_damage(10, true)) # 20Click Run to see what this code prints.
The _ready() Callback
Use case: _ready() is called automatically by Godot exactly once, right after a node (and all of its children) has fully entered the scene tree — the standard place to run setup code that depends on child nodes already existing.
extends Node
func _ready() -> void: print("This node and its children are ready.")Click Run to see what this code prints.
_process() vs _physics_process()
Use case: both callbacks run automatically on every frame, but for different purposes. _process(delta) runs once per rendered frame, ideal for visual updates. _physics_process(delta) runs at a fixed rate tied to the physics engine, the correct place for movement and collision-related logic.
extends Node2D
func _process(delta: float) -> void: rotation += delta # rotate smoothly, tied to render framerate
func _physics_process(delta: float) -> void: position.x += 100 * delta # movement, tied to the physics tickdelta is the elapsed time (in seconds) since the last call — multiplying a speed by delta, as shown above, keeps movement consistent regardless of frame rate, instead of moving faster on faster machines.
@onready Variables
Use case: @onready var defers a variable's initialization until right before _ready() runs, guaranteeing that any child-node lookups (like $Sprite2D from lesson 5) succeed, since the whole subtree is guaranteed to exist by that point.
extends CharacterBody2D
@onready var sprite: Sprite2D = $Sprite2D # safe: resolved right before _ready()
func _ready() -> void: print("Sprite found:", sprite != null)Click Run to see what this code prints.
Common Mistakes
- Putting movement logic in _process() instead of _physics_process(), causing frame-rate-dependent or jittery motion.
- Looking up a child node with $NodeName directly at the top of a script (outside @onready) — the node tree may not be built yet at that point.
- Forgetting to multiply by delta in per-frame logic, causing behavior to run at a different speed on different machines.
Best Practices
- Use _physics_process() for movement, collisions, and anything physics-related; use _process() for purely visual per-frame updates.
- Always multiply per-frame changes by delta so behavior stays consistent across different frame rates.
- Group @onready node references at the top of a script for a clear, scannable list of what a script depends on.
Frequently Asked Questions
No — implement only the ones a given script actually needs. Many scripts use just one, or neither.
Every node in the tree that has a script implementing _ready() gets its own call, in a defined order (children before their parent).
It signals "the engine calls this automatically" — a strong, consistent naming convention across all of Godot's built-in callback functions.
Key Takeaways
- Functions use func, with optional -> ReturnType annotations and default parameter values.
- _ready() runs once, automatically, after a node and its children have fully entered the scene tree.
- _process() runs per rendered frame; _physics_process() runs on a fixed physics tick — use the right one for the job.
- @onready defers a variable's setup until right before _ready(), making child-node lookups safe.
Summary
Functions and lifecycle callbacks are how your code actually runs inside Godot's engine loop. Next, you'll cover signals — GDScript's built-in event system for letting nodes talk to each other.