Skip to content
Make it work

Godot Autoload Singleton Guide: When to Use Global Scripts

A practical guide to Godot Autoloads and singletons. Learn what belongs in a global script, what should stay in scenes or Resources, and how to avoid messy project-wide state.

On this page

An autoload keeps a node available as you change scenes. That is useful for settings, music, or shared run data. It also lets scripts depend on a global object without showing that relationship in their scene, so it helps to decide what the autoload should own before adding one.

The short version: use Godot Autoloads for systems that truly belong to the whole game. Use scenes, signals, and Resources for almost everything else. If you are still shaping your project layout, read the Godot project structure guide first, then come back here and decide which scripts deserve to be global.

What an Autoload Actually Does

An Autoload is a script or scene that Godot creates when your project starts. You register it in Project Settings, give it a name, and then access that name from anywhere in GDScript. Many developers call this a singleton because there is one shared instance.

gdscript
# GameState.gd
extends Node

var coins: int = 0
var current_level: String = "level_01"

func add_coin(amount: int = 1) -> void:
    coins += amount

func reset_run() -> void:
    coins = 0
    current_level = "level_01"

After adding GameState.gd as an Autoload named GameState, any script can call GameState.add_coin(). That is convenient. The design question is whether every script should be allowed to know that global object exists.

Good Uses for Autoloads

The best Autoloads sit near the edge of your game. They coordinate things that outlive one scene and do not naturally belong to a single level object. They are not where every enemy stores its health.

  • SaveManager: reads and writes save files, then gives scenes clean data.
  • SceneLoader: handles level transitions, loading screens, and fade timing.
  • AudioManager: owns music, bus volume, mute settings, and crossfades.
  • Settings: stores resolution, input preferences, language, and accessibility options.
  • GameSession: tracks run-wide state in a roguelike, match, or campaign session.

A good test is simple: if you reload the current level, should this object survive? Save data, audio, and settings usually should. A door, a coin, a temporary buff, or one enemy's state usually should not.

What Not to Put in a Singleton

Do not use an Autoload because you do not want to pass references, connect signals, or think about ownership. That shortcut feels fast until your UI, player, enemies, and save system all depend on the same global script.

Scene-local state should stay scene-local. Item definitions should often be Godot Resources. UI should react through signals instead of constantly polling a global script. Practice that separation in the Scene Builder if the boundary still feels fuzzy.

A Cleaner SaveManager Pattern

Save systems are a sensible Autoload use case because saving and loading often cross scene boundaries. The trick is to keep the manager boring. Let it serialize data. Do not let it become the owner of every gameplay rule.

gdscript
# SaveManager.gd
extends Node

const SAVE_PATH := "user://save.json"

func save_game(data: Dictionary) -> void:
    var file := FileAccess.open(SAVE_PATH, FileAccess.WRITE)
    file.store_string(JSON.stringify(data))

func load_game() -> Dictionary:
    if not FileAccess.file_exists(SAVE_PATH):
        return {}

    var file := FileAccess.open(SAVE_PATH, FileAccess.READ)
    var parsed: Variant = JSON.parse_string(file.get_as_text())
    return parsed if parsed is Dictionary else {}

The level or player can decide what data to save. SaveManager only handles the file. For a longer walkthrough, pair this with the Save and Load guide.

How to Add an Autoload (Step by Step)

  • Write the script you want to be global, for example save_manager.gd, and save it in the project.
  • Open Project → Project Settings → Globals → Autoload.
  • Set Path to the script (or scene) and give it a Node Name: this is the identifier you will type in code.
  • Press Add. Leave the Enable column checked so the name resolves directly in GDScript.
  • Use it from anywhere: SaveManager.save_game(). No get_node(), no export reference.

Autoloads are created before the main scene and parented under the scene-tree root. They survive change_scene_to_file() because changing the current scene does not remove those nodes. Keep session-wide state there only when it needs that lifetime.

Autoload a Scene vs a Script vs a Resource

The Autoload path accepts either a script or a scene, and the choice is not cosmetic:

  • Script: Godot creates a bare Node and attaches the script. Right for pure logic: a signal bus, a save manager, a settings store.
  • Scene: the whole tree is instanced. Right when the global genuinely needs children: an audio manager with AudioStreamPlayer nodes, or a transition overlay with a CanvasLayer and ColorRect.
  • Resource: not autoloadable. A Resource is data, not a node, so it cannot be an Autoload. Load it inside an autoloaded script instead, which also keeps the saved data separate from the manager that writes it.

Fixing "class_name hides an autoload singleton"

This one confuses almost everybody the first time. You write a clean script, register it as an Autoload, and the editor complains that your class name hides an autoload singleton.

gdscript
# save_manager.gd
class_name SaveManager      # <-- global class named SaveManager
extends Node

func save_game() -> void:
    pass

# ...and the Autoload is ALSO named "SaveManager".
# Now one identifier means two different things.

A class_name registers a global type. An Autoload registers a global instance. Give them the same identifier and Godot cannot tell whether SaveManager means the class or the live node, so it warns you.

The fix is to stop naming both. Pick one:

  • Drop the class_name: usually correct. An autoloaded manager is a singleton instance; you rarely need it as a type too.
  • Or rename one of them: keep class_name SaveManagerClass and autoload it as SaveManager, if you genuinely need to reference the type elsewhere.

A Practical Rule of Thumb

Before making a script global, ask three questions: does it survive scene changes, does more than one unrelated scene need it, and would passing it manually make the code noisier instead of clearer? If the answer is yes to all three, an Autoload is probably fine.

Start with state in the scene that owns it. Move it into an autoload when it needs to survive scene changes or serve several independent scenes. This keeps local dependencies visible while giving shared systems a clear home.

Frequently asked questions

What is an Autoload in Godot?
An autoload is a node or scene that Godot loads before the main scene and keeps available across scene changes. It can hold shared state or services, but it does not prevent you from creating additional instances.
Are Autoloads the same as singletons?
Godot Autoloads are often used as singletons because they create one globally accessible instance. The important part is using them for true app-level systems, not as a dumping ground for every variable.
When should I avoid using an Autoload?
Avoid Autoloads when the data belongs to one scene, one enemy, one level, or one item. Use normal scene ownership, signals, or Resources instead.
Verification notes

Sources and revision context

Updated September 8, 2026. Clarified autoload ownership and initialization. Declared the JSON parse result as Variant after reproducing a compile failure; the smaller SaveManager received a parse check, not a save/load runtime test. This revision does not establish a full tutorial runtime test.