Godot Study Notes

Documenting my Godot game engine learning journey

This article will be updated over time (last updated: 2026.4.28)

Foreword

As the ancients said, reviewing the old helps one understand the new — so I’m taking notes while learning.

I figured I should learn something new, so I decided to learn the Godot engine to make the universe’s next breakout hit — a music game that’ll never see the light of day. Just an old saying.

Actually, before deciding what to learn, I considered whether to go with Godot or the more widely adopted Unity. But Godot had the following points that appealed to me:

  • Seems lightweight on performance

Unity feels very heavy to me. If I want to start a project, I need to launch Unity Hub, then Unity, then Visual Studio. That’s a lot of things to open, and I’m not sure my portable laptop can handle it. Godot, on the other hand, is a portable application that feels very lightweight.

  • GDScript seems easier to pick up

The games I’m planning to make are mostly 2D games. While there are specialized options like Cocos2D, my C++ skills are basically nonexistent, Java is still in its early stages, and learning C# looks like a winding path.

Godot’s native language, GDScript, is known for being as simple as Python. My actual experience confirms it’s easy to understand. Maybe learning GDScript will even help me pick up some Python skills along the way.

  • Unity keeps causing drama

I can’t be bothered to elaborate on this one.

I can’t think of other reasons right now — I haven’t reached a level where I can analyze them from a technical perspective. If I improve enough in the future or my needs change, I’ll consider learning other engines.

This article is based on Clear Code’s “Godot 4 Ultimate Beginner’s Tutorial.” Here’s the Bilibili link.

Key Concepts

Nodes

Nodes are a fundamental concept in Godot. A scene is a node, a player is a node — many things are nodes. The entire Godot engine is a big world of nodes.

In Godot, the basic workflow is creating various nodes and connecting them together. I personally think of them as multiple objects.

Main Screen

The image above shows Godot’s main interface. Press Ctrl + A to add a new node.

Nodes use PascalCase — each word starts with a capital letter. Other identifiers use snake_case — all lowercase with underscores. Godot handles this automatically.

Nodes have layer priority, similar to Photoshop — nodes lower in the hierarchy take priority.

Parent Nodes and Child Nodes

Nodes can contain other nodes. You can assign node B to node A. In this case, A is the parent node of B, and B is the child node.

Changes to properties in a parent node affect all child nodes, but not vice versa.

You can right-click on a parent node to add child nodes. To add an existing node as a child, press Ctrl + Shift + A or click “Instance Child Node” to see a list of all compatible nodes.

Language

Godot’s native language is GDScript. Although it’s marketed as being similar to Python, to be precise, it basically is Python. Apart from a few keyword differences, everything else is essentially the same.

All game properties can be found in the Inspector panel. Hovering over them will display the corresponding variable name.

Since Markdown doesn’t have native GDScript support, code blocks will use Python highlighting.

Language Features

  • Data types: Common data types are all covered; arrays cover both tuples and lists.

  • Two types of variables: Regular variables and constants

    Regular variable syntax:

    1
    2
    var name = 200 # General assignment
    var names: int = 114 # Typed assignment

    Constant syntax:

    1
    const value = 200 # General assignment
  • Functions: Used to implement functionality

    Python uses def as the function keyword, but GDScript uses func. The format is shown below:

    1
    2
    func name_here(vari a: int) -> bool # Parentheses for type hints, arrow for return type
    return true # Indentation indicates it still belongs to the function
  • Control flow: Includes if-else, for/while loops, continue/break, math operations, value comparisons, etc.

  • Classes: As I see it, nodes with functionality can be considered classes.

Built-in Functions

The game comes with two built-in functions, both starting with an underscore:

1
2
3
4
5
func _ready() -> void:
$logo.rotation_degrees = 90

func _process(delta: float) -> void:
pass

_ready — I call it the setup function. It runs once the node is ready.

_process — I call it the runtime function. It runs every frame.

Parent nodes can modify properties of child nodes. There are two ways to access them:

1
2
get_node("node path")
$node path # More commonly used

After typing, autocomplete will list all available child nodes.

For more detailed GDScript learning, check out my notes on Brackeys’ GDScript quick-start course.

Delta Time

Earlier I mentioned that the runtime function runs every frame, but this introduces a problem.

Suppose an object moves 10 pixels per frame. At 30 FPS, it moves 30 × 10 = 300 pixels. But if I’m running on the Sunway TaihuLight supercomputer, the framerate might hit 60, 120, or even 3000 FPS. That object would then move 600 pixels or more per second — way too fast to be playable.

I actually ran into a real example of this. When playing DJMAX TECHNIKA 2 on my computer, the countdown timer was going way too fast. After checking forums, I learned that this was because the game was originally developed for arcade machines with a 60Hz touchscreen. My monitor has a much higher refresh rate, which caused the game to run too quickly.

To solve this — ensuring consistent speed across machines with different frame rates — we need a unified time interval. That’s delta.

Delta time is the time it takes to render one frame. For example, delta at 30 FPS is 1s / 30f ≈ 0.0333.

Here’s how it works in practice:

Speed (pixels/frame) FPS Delta (seconds) Raw movement (pixels/sec) Delta-corrected movement (pixels/sec)
10 30 1 / 30 = 0.033 10 × 30 = 300 10 × 30 × 0.033 = 10
10 60 1 / 60 = 0.017 10 × 60 = 600 10 × 60 × 0.017 = 10
10 120 1 / 120 = 0.008 10 × 120 = 1200 10 × 120 × 0.008 = 10

As you can see, delta is multiplied by the raw movement speed to cancel out the effect of different frame rates, resulting in consistent movement speed.

In code, you multiply the desired value by delta:

1
2
pos.x += speed * delta
$logo.rotation_degrees += 45 * delta

Many functions will automatically incorporate delta in their calculations, so you won’t always need to think about it. Still, it’s an important concept to understand.

Getting Input

This is also covered in my GDScript notes — let me copy it here.

Getting input involves two steps:

1. Create Input Maps

Go to Project → Project Settings → Input Map.

Create a new action, click the “+” button, and bind a key. Here’s the example from the tutorial: create an action called my_action that changes a Label’s color when the spacebar is pressed.

2. Call Input Maps in Scripts

The built-in function for key bindings is _input:

1
2
3
4
5
6
func _input(event):
if is_action_pressed(my_action): # While holding the key
$Label.modulate = Color.RED

if is_action_released(my_action): # When releasing the key
$Label.modulate = Color.GREEN

There are two “pressed” functions to note: is_action_pressed and is_action_just_pressed. The key difference is that the former continuously checks the pressed state, while the latter only detects the initial press.

There’s a particularly useful function for 2D games: Input.get_vector. The parameter order is typically (negative_x, positive_x, negative_y, positive_y), corresponding to left, right, up, and down in the Godot coordinate system. Each execution adds 1 to the corresponding parameter.

Example:

1
2
3
4
# Set the direction variable using the function call
var direction = Input.get_vector("left", "right", "up", "down")
# Multiply by movement speed and delta time to move the sprite every frame
position = direction * 200 * delta

What About More Nodes?

Unique Name Access

In complex scenes, nodes can be deeply nested. Dragging a node directly into the editor will result in a very long path.

If a node is unique, you can right-click it and select “Access as Unique Name.”

Cross-Node Communication

In Godot, the most important thing is that nodes can access each other’s properties, so you need to understand how to connect them.

(To be improved)

Physics

The previous sections focused on moving a sprite around. But in games, sprites need to collide with each other, and there should be walls to constrain movement. This is where physics comes in.

Physics is the foundation of game movement. Images themselves don’t have collision properties — you need to use collision bodies and physics body nodes (like Area2D, PhysicsBody2D) to handle physical interactions.

Physics Types

CollisionObject and PhysicsBody are the foundation of physics properties. PhysicsBody includes three sub-types:

Name Definition Description
StaticBody Static collision body Cannot move on its own, but other objects can collide with it
CharacterBody Code-controlled entity Player or enemy driven by code; uses built-in methods for complex movement
RigidBody Physics body Moves only through physical forces (e.g., grenades); set initial velocity and it moves
Area Detection zone Detects when other objects enter its bounds
0条搜索结果。