Godot Coordinate Tutorial

Why Do My Objects Fly Away?

The Problem

Have you ever encountered this situation? You chop down a tree in your game, eagerly waiting for it to drop a log, but instead, the log instantly teleports to a far, distant location? This is a classic problem for Godot beginners, and its root lies in understanding the coordinate system.

Core Concepts: Local vs. Global Position

📍 position (Local Position)

A node's position relative to its "parent" node. It's like your position in a room, measured from the corner of that room.

🌍 global_position (Global Position)

A node's absolute position in the entire game world. It's like your latitude and longitude on Earth, measured from a fixed world origin.

Interactive Simulation

World (0, 0)
Level (Local: 72, 77)
🌳

Click a button to start the simulation...

❌ The Incorrect Way

Set position first, then add to scene tree.

func add_log_scene():
    var log = log_scene.instantiate()
    
    # Error! `log` is not in the scene yet.
    # Setting global_position has no effect.
    log.global_position = self.global_position
    
    get_parent().add_child(log)

Result: When `add_child` is called, Godot sets the log's local `position` to `(0,0)` because the previous global position assignment was invalid. This causes the log to appear at its parent's origin, not at the tree's location.

✅ The Correct Solution

Add to scene tree first, then set global position.

func add_log_scene():
    var log = log_scene.instantiate()
    
    # 1. Correct: Add `log` to the scene tree first.
    get_parent().add_child(log)
    
    # 2. After it's part of the scene,
    #    set its global_position.
    log.global_position = self.global_position

Result: When setting `global_position`, Godot knows who the log's parent is. It can then correctly calculate the required local `position` to place it precisely at the tree's location.

The Golden Rule

When you need to dynamically create an object and place it at a specific location in the world, always remember this order:

First `add_child()`, then set `global_position`.