Folder Layout & res:// Paths¶
What you'll learn
- The four top-level folders an idle/incremental project commits to early —
scenes/,scripts/,resources/,assets/— and what each one means. - What
res://actually resolves to, and why almost every path you type into Godot starts with it. - How the FileSystem dock relates to the folders on disk, and why those two views must stay in lockstep.
- Why folder layout is a coordinate-system decision in the same way the stretch settings were — picked once, expensive to change later.
How it applies
- Asset handoff with non-programmers. A sound designer handing you a folder of
.wavclips needs to know where to drop them. "Put them inassets/audio/sfx/" is a one-line answer. Without a layout, every new asset arrives in the project root and you spend the rest of the session re-filing them by hand. - Bug triage by folder. When a QA report says "the upgrade panel shows the wrong icon," knowing the panel's scene lives under
scenes/ui/and the icon lives underassets/icons/upgrades/cuts the file-search time. A flat project means scrolling a wall of files looking for the right.tres. - Diff readability in source control.
git diffover a per-folder structure tells the reviewer at a glance what changed: ascenes/ui/change is UI; ascripts/autoloads/change is global state. A flat structure produces diff reports that all look the same — UI fixes, balance changes, save-system rewrites all blend together in code review. - Export filtering for shipped builds. Godot's export presets let you include or exclude folders. A
assets/raw/folder of source-quality art (50× larger than the in-game versions) can be excluded from the released build — but only if there is a folder boundary to exclude on. Flat projects ship every loose file. - Refactor blast radius. When you eventually rename a folder — and you will, mid-project — every
res://path that pointed inside it must update. Godot 4.6's UID system (uid://...) absorbs most of this for.tscn/.tresreferences, but raw text paths (signals connected to scripts, save-file path strings, exported variables holding paths) do not get UIDs. The fewer renames, the fewer manual fix-ups. Pick the folder names you can live with. - Onboarding the next person. Idle games are often hobby projects passed between collaborators. A predictable folder layout is the difference between a new contributor finding the click-button scene in 30 seconds and bouncing off the project after 20 minutes of cold reading.
Concepts¶
The FileSystem dock and res://¶
Every Godot project has a single root directory on disk — the directory containing project.godot. For our project, that is C:\Users\danyf\source\repos\godot-idle-learning\. The FileSystem dock, the panel in the bottom-left of the editor by default, is a live view of that directory. Files added on disk show up in the dock; files dragged in the dock get moved on disk.
Inside the engine, that root directory is referred to as res://. Any file path you type into Godot — a scene reference, a script reference, a sound clip path — starts with res:// and is interpreted relative to the project root. res://scenes/main.tscn is the file <project root>\scenes\main.tscn on disk. The engine never lets you reach files outside res:// from runtime code; the prefix is also a sandbox boundary.
There is also user://, which resolves to a per-OS user-data directory (something like %APPDATA%\Godot\app_userdata\Blood Knight Grove\ on Windows). That is for save files and runtime-written data. We will use it in M7.
Example
You write preload("res://scripts/autoloads/tick.gd") in a future script. The engine looks at the project root, descends into scripts/, then autoloads/, then loads tick.gd. If you move that file to scripts/systems/tick.gd later, every preload and load call referencing the old path silently fails at run time — no compile-time check catches it. The UID system covers .tscn and .tres references but does not cover preload calls against .gd files.
Example
A common confusion: the FileSystem dock and Windows Explorer are looking at the same files. If you open the project root in Explorer and create a folder called notes/ there, that folder shows up in the FileSystem dock the next time the editor refocuses. If you create the folder via the FileSystem dock instead, Windows Explorer sees it on the next refresh. They are two windows onto the same disk state — never out of sync for long.
The four top-level folders¶
For Blood Knight Grove and any other idle/incremental project, the project root grows four top-level folders early. Each one has a single purpose:
scenes/—.tscnfiles. The composition trees of nodes that make up the game's screens, panels, rows, popups. Sub-folders by purpose:scenes/ui/for menus and HUD, eventuallyscenes/buildings/for per-generator scenes if those scale up.scripts/—.gdfiles. The behavior code attached to scenes, plus autoloads. Sub-folders:scripts/autoloads/for global singletons, eventuallyscripts/systems/for cross-cutting logic.resources/—.tresfiles. Custom data containers — yourUpgradeData,BuildingData, etc. These are pure data, not scenes; they will drive the upgrade and building systems in M4 and M5. Sub-folders:resources/buildings/,resources/upgrades/.assets/— raw inputs the engine consumes:.png,.wav,.ogg, fonts, shaders. Sub-folders:assets/sprites/,assets/audio/sfx/,assets/audio/music/,assets/fonts/. The convention is "anything an artist or sound designer can drop in" lives here.
The discipline behind the split: scenes describe structure, scripts describe behavior, resources describe data, assets are raw inputs. When you cannot decide where a file goes, you almost always have not asked which of those four it is.
Example
A new .tres file containing the click upgrade's name, cost, and effect multiplier goes in resources/upgrades/click_power_1.tres. It is data — not a scene, not behavior, not raw asset input.
Example
A .gd script that defines the UpgradeData class (the schema for what fields any upgrade resource has) goes in scripts/upgrade_data.gd. The script is behavior + schema; the individual .tres files that conform to that schema are data. Putting the class definition under resources/ would be wrong — resources/ is for instances, not for the type itself.
Example
A new button click sound. The .wav file goes in assets/audio/sfx/click.wav. The Godot AudioStream asset that wraps it (auto-generated when the engine imports the file) lives alongside it. The scene that plays the sound — an AudioStreamPlayer node — is part of whatever UI scene needs the click, so it lives in scenes/ui/.
Folder layout as a coordinate system¶
In M1.1 you committed to a base resolution and stretch behavior. Every later anchor and font-size decision was calibrated against 1280×720. The folder layout is the same kind of commitment, on the file-system axis instead of the pixel axis.
Once you start writing preload("res://scripts/autoloads/tick.gd") in M3, that path string is hard-coded into the codebase. So is the .tres path the resource browser remembers when you assign an UpgradeData to a slot in the inspector. Renaming scripts/autoloads/ to scripts/globals/ later is a search-and-replace operation across every file that referenced the old name — and as noted, the UID system covers some references but not all of them. Picking the names you can live with at the start of M1 is the cheap version of this decision; picking them at the start of M5 is the expensive version.
This is also why the convention is conservative — scenes/, scripts/, resources/, assets/ are the names every Godot tutorial and template uses. Inventing your own (game_logic/, data_structures/, art/) makes your project harder to read for anyone with Godot experience, including future-you in six months.
Example
A project that starts with code/ for scripts and art/ for assets is internally consistent but reads as "non-standard" to anyone else. When you eventually pull a snippet from a Godot forum or paste a community plugin, both will assume scripts/ and assets/ exist. You will end up either renaming yours or maintaining two parallel conventions. The cost is small but real.
Sub-folder-as-you-go¶
The four top-level folders are committed to at the start. Sub-folders inside them are added as the project needs them. Right now M1 needs no sub-folders — scenes/main.tscn is the only file that will live anywhere, and it goes directly under scenes/. By M3 you will have scripts/autoloads/tick.gd, so scripts/autoloads/ is born. By M5 you may have a dozen BuildingData resources, so resources/buildings/ is born.
Do not pre-create empty sub-folders for files that do not exist yet. Empty folders read as forgotten work-in-progress; they bloat the FileSystem dock; they survive in git only if you remember to add a .gitkeep. Wait until the second file is about to land in a top-level folder, and then group the existing one into a sub-folder.
Example
M1 ends with exactly one scene: scenes/main.tscn. There is no scenes/ui/ folder yet, even though M1.4 will populate that scene with UI nodes. The folder is created in M2 when the second UI scene (the click button, broken out of Main) needs a home.
Walkthrough¶
You will perform these in your own Godot editor, with the godot-idle-learning project open.
- Locate the FileSystem dock. It is the panel in the bottom-left of the editor by default. The top entry is
res://; expanding it shows the project root. - Right-click on
res://in the FileSystem dock. From the context menu, choose New Folder…. A small modal opens with a text field. - Type
scenes(lowercase, no trailing slash) and press Enter. The folder appears underres://. - Repeat steps 2–3 for
scripts,resources, andassets. The FileSystem dock should now show four sibling folders underres://. - Switch to Windows Explorer, navigate to the project root (
C:\Users\danyf\source\repos\godot-idle-learning\), and confirm the four directories exist on disk. They should. (If they don't, you created them somewhere else — drag them into place in the FileSystem dock.) - Back in the editor, do not create any sub-folders yet. There are no files to put in them.
- Save-state check: the four top-level folders are not yet committed to source control. They are also empty, which means
git statusshows no change —gitonly tracks files. This is fine. The first scene you save in M1.3 will land underscenes/, and that file will pull the folder along with it.
Optional sanity check. From the FileSystem dock, click on
res://scenesto select it. The bottom of the dock shows the path asres://scenes. Now click on the folder in the main viewport area — there is no main-viewport effect because folders are not scenes. The dock is the only place the folder is visible inside the editor; that is normal.
Self-check quiz¶
Q1 — In Godot, what does the path res://scripts/autoloads/tick.gd actually resolve to on disk for this project?
A. The Godot engine's installation directory plus scripts/autoloads/tick.gd.
B. The project root (the folder containing project.godot) plus scripts/autoloads/tick.gd.
C. The user data directory (%APPDATA%\Godot\...) plus scripts/autoloads/tick.gd.
D. The current working directory the engine was launched from, plus scripts/autoloads/tick.gd.
Reveal answer
B — the project root. res:// is always the directory containing project.godot, regardless of where the engine binary lives or how it was launched. A is wrong: the engine install dir is unrelated to user projects. C confuses res:// with user://, which is the per-user appdata path used for save files. D is what res:// would mean in a poorly-designed engine; Godot intentionally pins res:// to the project so that running the same project from a different shell produces the same paths.
Q2 — You finish writing the GDScript class that defines what fields every UpgradeData resource has. Where does that .gd file go?
A. resources/upgrades/upgrade_data.gd — it goes with the upgrade resources.
B. scripts/upgrade_data.gd — it is behavior/schema code, even though instances of it live elsewhere.
C. assets/upgrade_data.gd — it is a project asset.
D. scenes/ui/upgrade_data.gd — the upgrade UI uses it most.
Reveal answer
B — scripts/upgrade_data.gd. The class definition is GDScript code; it goes under scripts/. The instances of that class — the individual .tres files for the click-power upgrade, the prestige upgrade, etc. — go under resources/upgrades/. A is the most common confusion: pure data files live with their kind, but the schema describing the data lives with the code. C is wrong because assets/ is for raw inputs (PNGs, WAVs, fonts) — not scripts. D conflates the script with the consumer; many UI scenes will reference UpgradeData, and putting the schema in any one of them would force the others to depend on UI code.
Q3 — At the end of M1, the project has exactly one scene file (scenes/main.tscn). Should you also create scenes/ui/, scripts/autoloads/, resources/upgrades/, and assets/sprites/ now to 'have them ready'?
A. Yes — pre-creating the full sub-folder tree gives the project a finished feel and prevents forgetting.
B. Yes for scripts/autoloads/ (which the editor needs for autoload registration), no for the others.
C. No — empty folders bloat the dock, are not tracked by git, and signal forgotten work-in-progress. Create each sub-folder when the second file is about to land in its parent.
D. Only if you commit a .gitkeep in each so git does track them.
Reveal answer
C — create sub-folders only when there is something to put in them. The dock and git both stay clean. B is plausible-sounding but wrong: the autoload registration mechanism (Project Settings → Globals → Autoload) lets you point at any path; it does not require scripts/autoloads/ to pre-exist. D is a workaround for a problem that does not need solving — the .gitkeep convention exists for cases where an empty directory is a deliverable (e.g., a runtime cache directory), which does not apply here.
Integration question¶
Q4 — open
In M1.1 you committed to base resolution 1280×720 and Aspect = keep. In M1.2 you committed to four top-level folders. Both decisions are described in this textbook as coordinate-system commitments. What property do they share, and what is the cost of getting either of them wrong now versus later?
Reveal expected answer
Both decisions become the meaning of countless later expressions. The stretch settings define what every anchor numeric (anchor_top = 0.4) means in the player's window; the folder layout defines what every res:// path string means on disk. Once any later module starts referencing those values — anchors in M1.4, paths in M2.1 — every file that uses them is calibrated against the original choice. A late change to either requires re-checking every reference. Doing it now is a five-second decision; doing it after M5 is a multi-hour search-and-replace, with the additional risk that some references (string literals in save files, paths in comments) will be missed and silently break.
Glossary¶
Glossary
- FileSystem dock
- The editor panel (bottom-left by default) showing a live view of the project root directory. Files added on disk appear here; drags within the dock move files on disk.
res://- The path prefix that resolves to the project root (the directory containing
project.godot). All in-game asset paths start with this. Sandboxed — runtime code cannot reach above it. user://- The path prefix resolving to a per-OS user-data directory (e.g.,
%APPDATA%\Godot\app_userdata\Blood Knight Grove\on Windows). For save files and any runtime-written data. Distinct fromres://, which is read-only at runtime. .tscnfile- On-disk format of a Godot scene. Text-based, human-readable, diff-friendly. Stores a tree of nodes plus their properties. One scene per file.
.tresfile- On-disk format of a Godot Resource. Text-based. Stores instances of any class extending Resource — typically custom data containers like
UpgradeData,BuildingData. Pure data, not behavior. .gdfile- GDScript source file. Behavior code attached to nodes via the script slot, plus autoload globals.
- autoload
- Globally-available singleton configured in
Project Settings → Globals → Autoload. Loaded once at game start, accessible from any scene by name (e.g.,Tick.tick_rate). For cross-scene state and systems. preload(...)- GDScript built-in that loads a resource at parse time (when the script is first compiled), not at runtime. Path is a string literal — fails silently if the target is renamed without updating the call. Distinct from
load(), which runs at the call site. - UID system
- Godot 4.x's stable-identifier indirection. Each
.tscn/.tresgets auid://reference stored in a.uidsidecar file. Scene/resource references survive renames because the engine resolves the UID rather than the path. Does not cover.gdpreload()s or string-literal paths.