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

  1. Run the project and open Editor → Debugger (or the bottom Debugger dock).
  2. Open the Monitors tab.
  3. 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

  1. Open Debugger → Profiler.
  2. Click Start before you trigger heavy gameplay, then Stop after 10–20 seconds.
  3. 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.

  1. Open each GPUParticles2D (or CPUParticles2D if you use them) and note Amount, Lifetime, and whether One Shot is on.
  2. Rule of thumb for a jam slice: keep Amount under a few hundred total on screen and prefer short lifetimes plus one-shot bursts.
  3. Pool reusable FX if you spawn the same scene dozens of times per second. A simple array of hidden Node2D previews, activated and recycled, beats instantiate + queue_free in 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 = false on 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.

  1. Select textures in FileSystem and review the Import dock. Prefer VRAM Compressed for color art where banding is acceptable; use Lossless only when necessary.
  2. Atlas small UI and prop sprites so one material batch covers many quads.
  3. 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_SHOT for one-off UI, or disconnect in _exit_tree().

SaveGame autoload from Lesson 11

  • If deserialize paths create duplicate nodes (double add_child of the same scene), object counts rise each load.
  • Always queue_free old dynamic level roots before instantiating a fresh copy from current_scene_path.

Step 7: Visibility and off-screen work

  1. For props that animate or tick AI while off camera, add VisibleOnScreenNotifier2D and pause logic when screen_entered / screen_exited flip.
  2. 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

  1. Record FPS and Process before and after spawning 30 enemies. If Process rises after they die, fix cleanup.
  2. Cap every GPUParticles2D in combat so total on-screen particles stay under a self-chosen budget (write the number in README for your team).
  3. 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.

Layangan kite artwork by Dribbble artist