Lesson Goal
Exports do not forgive mistakes the editor hid. A steady 60 FPS in a dev scene can collapse when particles, enemy count, or GUI redraw spike.
By the end of this lesson, you will:
- read Debugger → Monitors and know which graphs matter for a 2D action slice
- capture a Profiler sample while combat and UI from Lesson 10 run together
- apply budgets to
GPUParticles2D, physics bodies, and drawn tiles from Lesson 6 - spot reference leaks that make long sessions balloon RAM after Lesson 11
Step 1: Enable the monitors you actually need
- Run the project and open Editor → Debugger (or the bottom Debugger dock).
- Open the Monitors tab.
- Watch these for a 2D action game (names may vary slightly by Godot 4.x minor version):
| Monitor | Why |
|---|---|
| FPS | Baseline; test on your slowest machine, not only your laptop. |
| Process | Node count; climbing during idle usually means leaks or runaway spawns. |
| Object | Live Object instances; pairs with Process for leak hunts. |
| Physics | Active RigidBody2D / CharacterBody2D cost when you swarm enemies from Lesson 5. |
| Draw (2D primitives) | Sudden jumps when VFX or damage numbers batch poorly. |
Pro tip: Dock Monitors beside the running game. Stress the worst encounter (many enemies + hitstop + screen shake) for 60 seconds. If Process never plateaus, you have homework.
Step 2: Use the Profiler for frame budget truth
- Open Debugger → Profiler.
- Click Start before you trigger heavy gameplay, then Stop after 10–20 seconds.
- Inspect Physics Process, Process, Idle, and Navigation (if you use it). Long bars mean that stage owns the frame.
Common pattern: UI trees that rebuild every frame show up under Canvas Item or GUI-related profiler categories. If your inventory label from Lesson 8 re-instantiates controls instead of updating text, fix that before polishing art.
Step 3: Particle and VFX caps
Hit sparks and death puffs from combat lessons are easy to over-spawn.
- Open each
GPUParticles2D(orCPUParticles2Dif you use them) and note Amount, Lifetime, and whether One Shot is on. - Rule of thumb for a jam slice: keep Amount under a few hundred total on screen and prefer short lifetimes plus one-shot bursts.
- Pool reusable FX if you spawn the same scene dozens of times per second. A simple array of hidden
Node2Dpreviews, activated and recycled, beatsinstantiate+queue_freein a tight loop.
Common mistake: Forgetting to queue_free() temporary FX scenes. They leave orphan nodes until the parent cleans up.
Step 4: Physics and collision hygiene
From Lesson 4 you likely mix Area2D hitboxes with CharacterBody2D movement.
- Keep collision layers/masks tight so broad-phase work stays small.
- Disable monitoring or set
monitoring = falseon areas that do not need ticks. - Avoid hundreds of tiny RigidBody2D props unless the game needs them; StaticBody2D or tile collision is cheaper.
Step 5: Textures, atlases, and import defaults
Large PNGs for characters and tiles multiply GPU memory.
- Select textures in FileSystem and review the Import dock. Prefer VRAM Compressed for color art where banding is acceptable; use Lossless only when necessary.
- Atlas small UI and prop sprites so one material batch covers many quads.
- After changing import settings, click Reimport once so builds pick up the new format.
Step 6: Memory leaks from signals and saves
Two frequent Godot foot-guns:
Signals
- Connecting lambdas or callables to long-lived autoloads without ever disconnecting keeps targets alive.
- Prefer
CONNECT_ONE_SHOTfor one-off UI, or disconnect in_exit_tree().
SaveGame autoload from Lesson 11
- If deserialize paths create duplicate nodes (double
add_childof the same scene), object counts rise each load. - Always
queue_freeold dynamic level roots before instantiating a fresh copy fromcurrent_scene_path.
Step 7: Visibility and off-screen work
- For props that animate or tick AI while off camera, add
VisibleOnScreenNotifier2Dand pause logic whenscreen_entered/screen_exitedflip. - Large tilemaps from Lesson 6 are efficient, but decoration layers with thousands of sprites still cost draw calls; merge where you can.
Troubleshooting
| Symptom | Likely cause | Quick check |
|---|---|---|
| FPS dives only in builds | Different renderer settings vs editor; missing GPU on target | Export a release build with logging; compare Display project settings. |
| RAM grows when opening menus | GUI scene duplicated every open | Ensure you queue_free old menu or use singleton UI shell. |
| Stutter every few seconds | GC or shader compile blips | Profiler; reduce allocations in hot paths; warm up shaders in a loading screen. |
| Physics spikes with many enemies | Too many active bodies or broad contacts | Reduce mask overlap; simplify hitbox shapes. |
FAQ
Should I optimize before gameplay is fun?
No. Lock fun first, then kill the top profiler bar. This lesson is about knowing how to measure, not premature polish.
Is Remote Scene Tree debugging worth it?
Yes for mobile or console targets later. For now, editor monitors plus occasional export builds are enough.
Do I need LOD for 2D?
Rarely at indie scale. Prefer fewer sprites, atlases, and shorter particle lifetimes before inventing LOD.
Mini challenge
- Record FPS and Process before and after spawning 30 enemies. If Process rises after they die, fix cleanup.
- Cap every
GPUParticles2Din combat so total on-screen particles stay under a self-chosen budget (write the number inREADMEfor your team). - Load a save, play 5 minutes, reload three times. Object count should return to a similar baseline after each load.
Summary
- Monitors tell you if the game is stable under stress; Profiler tells you who ate the frame.
- Particles, physics, and GUI rebuilds are the usual 2D action culprits.
- Imports and atlases control VRAM; signals and scene reload control reference leaks.
Next you will wire export presets, icons, and version strings for desktop and web. Continue to Lesson 13: Export Presets and Packaging.
For more Godot depth, keep the Performance Debugging in Godot 4 chapter open while you profile.
