/godot-optimization
Use when optimizing Godot games — profiler, draw calls, physics tuning, memory management, and common bottlenecks
$ npx -y skills add jame581/GodotPrompter --skill godot-optimization --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/godot-optimization
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use when optimizing Godot games — profiler, draw calls, physics tuning, memory management, and common bottlenecks
SKILL.md
godot-optimization.SKILL.mdname: godot-optimization
description: Use when optimizing Godot games — profiler, draw calls, physics tuning, memory management, and common bottlenecks
Godot Optimization
This skill covers performance optimization for Godot 4.3+ projects in both GDScript and C#. It covers the built-in profiler, draw call reduction, physics tuning, GDScript performance patterns, memory management, object pooling, and a reference table of common bottlenecks.
> **Related skills:** **godot-debugging** for systematic debugging and profiling, **godot-code-review** for performance review checklist, **export-pipeline** for release build optimization, **physics-system** for collision shapes, layers, and physics body types, **2d-essentials** for 2D mesh optimization, particle performance, and draw order tuning, **multithreading** for moving work off the main thread, **mobile-development** for mobile performance budgets.
---
1. Using the Profiler
Frame Time Budget
At 60 fps, the entire frame (update, physics, rendering) must complete in **16.6 ms**. At 30 fps the budget is 33.3 ms. Any single system that consumes the majority of that budget is a bottleneck.
| Target FPS | Frame budget | |---|---| | 120 | 8.3 ms | | 60 | 16.6 ms | | 30 | 33.3 ms |
Reading Profiler Output
Open **Debugger > Profiler**, click **Start**, play through the scenario you want to measure, then click **Stop**.
- **Frame Time** — total wall-clock time for that frame in milliseconds.
- **Self** — time spent inside that function *excluding* callees. This is the primary hotspot indicator. A function with a high Self time is doing expensive work directly.
- **Total** — time including all callees. Useful for identifying expensive subtrees.
- **Calls** — call count per frame. A function called thousands of times per frame (even if each call is cheap) can dominate the frame.
- Click any function name to jump to its source in the script editor.
# Manual micro-benchmark for a specific block
var start := Time.get_ticks_usec()
_run_expensive_operation()
var elapsed := Time.get_ticks_usec() - start
print("_run_expensive_operation: %d µs" % elapsed)**C#:**
// Manual micro-benchmark using Stopwatch (high-resolution timer)
using System.Diagnostics;
var sw = Stopwatch.StartNew();
RunExpensiveOperation();
sw.Stop();
GD.Print($"RunExpensiveOperation: {sw.Elapsed.TotalMilliseconds:F3} ms");
// Alternative using Godot's built-in timer (microsecond precision)
long start = (long)Time.GetTicksUsec();
RunExpensiveOperation();
long elapsed = (long)Time.GetTicksUsec() - start;
GD.Print($"RunExpensiveOperation: {elapsed} µs");Monitors Tab
**Debugger > Monitors** shows real-time engine metrics while the game is running. Click a monitor name to open a live graph. Key monitors to watch:
| Monitor | What to watch for | |---|---| | `Time > FPS` | Below target — frame budget overrun | | `Time > Process` | High — `_process()` callbacks are expensive | | `Time > Physics Process` | High — `_physics_process()` or physics sim is expensive | | `Render > Total Draw Calls` | Above ~500 (mobile) or ~2 000 (desktop) — needs batching | | `Render > Video RAM` | Steadily growing — unfreed textures or meshes (memory leak) | | `Object > Object Count` | Growing across scene reloads — nodes are not being freed | | `Physics 3D > Active Bodies` | Large count in simple scenes — bodies not sleeping |
# Query any monitor at runtime from code
var fps := Performance.get_monitor(Performance.TIME_FPS)
var draw_calls := Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME)
var video_ram := Performance.get_monitor(Performance.RENDER_VIDEO_MEM_USED)
print("FPS: %d | Draw calls: %d | VRAM: %.1f MB" % [fps, draw_calls, video_ram / 1_048_576.0])**C#:**
// Query any monitor at runtime from code
double fps = Performance.GetMonitor(Performance.Monitor.TimeFps);
double drawCalls = Performance.GetMonitor(Performance.Monitor.RenderTotalDrawCallsInFrame);
double videoRam = Performance.GetMonitor(Performance.Monitor.RenderVideoMemUsed);
GD.Print($"FPS: {fps:F0} | Draw calls: {drawCalls:F0} | VRAM: {videoRam / 1_048_576.0:F1} MB");---
2. Draw Call Optimization
Every distinct mesh, sprite, or canvas item that cannot be batched with its neighbours costs one draw call. Reducing draw calls is one of the highest-leverage optimisations, especially on mobile — wrap 2D groups sharing a texture in `CanvasGroup`, keep unique-material count low, atlas sprites, and cull off-screen work.
> See [references/draw-calls.md](references/draw-calls.md) for the full recipes (CanvasGroup batching constraints, shared shader-parameter materials, texture atlases, `VisibleOnScreenNotifier2D/3D` culling, and 3D LOD swapping).
---
3. Physics Optimization
Physics tuning hinges on minimising broadphase work and avoiding mesh colliders on moving bodies. Trim collision masks to only the layers each body actually needs, replace `ConcavePolygonShape3D` with primitives on anything that moves, and prefer `Area2D/3D` over per-frame raycasts for overlap detection.
> See [references/physics-tuning.md](references/physics-tuning.md) for the full recipes (layer/mask bit examples, collision-shape cost table, `Engine.physics_ticks_per_second` tuning, Area-vs-raycast patterns).
---
4. GDScript Performance
Hot-path GDScript wins come from eliminating per-frame allocations, comparing `StringName` instead of `String`, using typed arrays / `PackedArray`s, and `preload`-ing resources at class scope. The same allocation discipline applies to C# (with `List<T>` in place of typed `Array[T]` and `static readonly StringName` fields).
> See [references/cpu-bottlenecks.md](references/cpu-bottlenecks.md) for the full recipes (cached group queries, reused vector locals, `&"..."` literals, `PackedVector2Array`, static typing, `preload` vs `load`, plus C# parity blocks).
---
5. Memory Management
Watch `Performance.MEMORY_STA
Read more
name: godot-optimization description: Use when optimizing Godot games — profiler, draw calls, physics tuning, memory management, and common bottlenecks
Godot Optimization
This skill covers performance optimization for Godot 4.3+ projects in both GDScript and C#. It covers the built-in profiler, draw call reduction, physics tuning, GDScript performance patterns, memory management, object pooling, and a reference table of common bottlenecks.
> **Related skills:** **godot-debugging** for systematic debugging and profiling, **godot-code-review** for performance review checklist, **export-pipeline** for release build optimization, **physics-system** for collision shapes, layers, and physics body types, **2d-essentials** for 2D mesh optimization, particle performance, and draw order tuning, **multithreading** for moving work off the main thread, **mobile-development** for mobile performance budgets.
---
1. Using the Profiler
Frame Time Budget
At 60 fps, the entire frame (update, physics, rendering) must complete in **16.6 ms**. At 30 fps the budget is 33.3 ms. Any single system that consumes the majority of that budget is a bottleneck.
| Target FPS | Frame budget | |---|---| | 120 | 8.3 ms | | 60 | 16.6 ms | | 30 | 33.3 ms |
Reading Profiler Output
Open **Debugger > Profiler**, click **Start**, play through the scenario you want to measure, then click **Stop**.
- **Frame Time** — total wall-clock time for that frame in milliseconds.
- **Self** — time spent inside that function *excluding* callees. This is the primary hotspot indicator. A function with a high Self time is doing expensive work directly.
- **Total** — time including all callees. Useful for identifying expensive subtrees.
- **Calls** — call count per frame. A function called thousands of times per frame (even if each call is cheap) can dominate the frame.
- Click any function name to jump to its source in the script editor.
# Manual micro-benchmark for a specific block
var start := Time.get_ticks_usec()
_run_expensive_operation()
var elapsed := Time.get_ticks_usec() - start
print("_run_expensive_operation: %d µs" % elapsed)**C#:**
// Manual micro-benchmark using Stopwatch (high-resolution timer)
using System.Diagnostics;
var sw = Stopwatch.StartNew();
RunExpensiveOperation();
sw.Stop();
GD.Print($"RunExpensiveOperation: {sw.Elapsed.TotalMilliseconds:F3} ms");
// Alternative using Godot's built-in timer (microsecond precision)
long start = (long)Time.GetTicksUsec();
RunExpensiveOperation();
long elapsed = (long)Time.GetTicksUsec() - start;
GD.Print($"RunExpensiveOperation: {elapsed} µs");Monitors Tab
**Debugger > Monitors** shows real-time engine metrics while the game is running. Click a monitor name to open a live graph. Key monitors to watch:
| Monitor | What to watch for | |---|---| | `Time > FPS` | Below target — frame budget overrun | | `Time > Process` | High — `_process()` callbacks are expensive | | `Time > Physics Process` | High — `_physics_process()` or physics sim is expensive | | `Render > Total Draw Calls` | Above ~500 (mobile) or ~2 000 (desktop) — needs batching | | `Render > Video RAM` | Steadily growing — unfreed textures or meshes (memory leak) | | `Object > Object Count` | Growing across scene reloads — nodes are not being freed | | `Physics 3D > Active Bodies` | Large count in simple scenes — bodies not sleeping |
# Query any monitor at runtime from code
var fps := Performance.get_monitor(Performance.TIME_FPS)
var draw_calls := Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME)
var video_ram := Performance.get_monitor(Performance.RENDER_VIDEO_MEM_USED)
print("FPS: %d | Draw calls: %d | VRAM: %.1f MB" % [fps, draw_calls, video_ram / 1_048_576.0])**C#:**
// Query any monitor at runtime from code
double fps = Performance.GetMonitor(Performance.Monitor.TimeFps);
double drawCalls = Performance.GetMonitor(Performance.Monitor.RenderTotalDrawCallsInFrame);
double videoRam = Performance.GetMonitor(Performance.Monitor.RenderVideoMemUsed);
GD.Print($"FPS: {fps:F0} | Draw calls: {drawCalls:F0} | VRAM: {videoRam / 1_048_576.0:F1} MB");---
2. Draw Call Optimization
Every distinct mesh, sprite, or canvas item that cannot be batched with its neighbours costs one draw call. Reducing draw calls is one of the highest-leverage optimisations, especially on mobile — wrap 2D groups sharing a texture in `CanvasGroup`, keep unique-material count low, atlas sprites, and cull off-screen work.
> See [references/draw-calls.md](references/draw-calls.md) for the full recipes (CanvasGroup batching constraints, shared shader-parameter materials, texture atlases, `VisibleOnScreenNotifier2D/3D` culling, and 3D LOD swapping).
---
3. Physics Optimization
Physics tuning hinges on minimising broadphase work and avoiding mesh colliders on moving bodies. Trim collision masks to only the layers each body actually needs, replace `ConcavePolygonShape3D` with primitives on anything that moves, and prefer `Area2D/3D` over per-frame raycasts for overlap detection.
> See [references/physics-tuning.md](references/physics-tuning.md) for the full recipes (layer/mask bit examples, collision-shape cost table, `Engine.physics_ticks_per_second` tuning, Area-vs-raycast patterns).
---
4. GDScript Performance
Hot-path GDScript wins come from eliminating per-frame allocations, comparing `StringName` instead of `String`, using typed arrays / `PackedArray`s, and `preload`-ing resources at class scope. The same allocation discipline applies to C# (with `List<T>` in place of typed `Array[T]` and `static readonly StringName` fields).
> See [references/cpu-bottlenecks.md](references/cpu-bottlenecks.md) for the full recipes (cached group queries, reused vector locals, `&"..."` literals, `PackedVector2Array`, static typing, `preload` vs `load`, plus C# parity blocks).
---
5. Memory Management
Watch `Performance.MEMORY_STA
Agentic skills framework for Godot 4.x game development. Gives AI coding agents domain-specific expertise for GDScript and C# projects.
Other skills on godot-prompter.
- /authoring-godot-prompter-skills
Use when writing or editing a SKILL.md or an agent definition in this repo — required frontmatter, section ordering, and the GDScript-then-C# example convention.
Open skill - /releasing-godot-prompter
Use when cutting a GodotPrompter release or bumping its version — the version-bump sequence, tag-triggered workflow, and the marketplace manifests that must follow.
Open skill - /2d-essentials
Use when working with 2D-specific systems — TileMaps, parallax scrolling, 2D lights and shadows, canvas layers, particles 2D, custom drawing, and 2D meshes in Godot 4.3+
Open skill - /3d-essentials
Use when working with 3D-specific systems — materials, lighting, shadows, environment, global illumination, fog, LOD, occlusion culling, and decals in Godot 4.3+
Open skill - /ability-system
Use when building character abilities — Resource-based abilities with cost/cooldown/cast, buffs/debuffs, stat modifiers, gameplay tags, and HUD binding
Open skill - /addon-development
Use when creating Godot editor plugins — EditorPlugin, @tool scripts, custom inspectors, and dock panels
Open skill

