NEVER Do in Performance Optimization
- NEVER optimize without profiling first — "I think physics is slow" without data? Premature optimization. ALWAYS use Debug → Profiler (F3) to identify actual bottleneck [20].
- NEVER use
print()in release builds —print()every frame = file I/O bottleneck + log spam. Use@warning_ignoreor conditionalif OS.is_debug_build():[21]. - NEVER ignore
VisibleOnScreenNotifier2Dfor off-screen entities — Enemies processing logic off-screen = wasted CPU. Disableset_process(false)whenscreen_exited[22]. - NEVER instantiate nodes in hot loops —
for i in 1000: var bullet = Bullet.new()= 1000 allocations. Use object pools, reuse instances [23]. - NEVER use
get_node()in_process()— Callingget_node("Player")60x/sec = tree traversal spam. Cache in@onready var player := $Player[24]. - NEVER forget to batch draw calls — 1000 unique sprites = 1000 draw calls. Use TextureAtlas (sprite sheets) + MultiMesh for instanced rendering [25].
- NEVER block the main thread for heavy operations — Avoid
OS.delay_msec()or long synchronous data processing. UseWorkerThreadPoolto keep framerates steady. - NEVER use complex collision shapes for physics queries — High-poly convex shapes are expensive to resolve. Prefer simplified primitives (Circle, Rectangle, Box).
- NEVER forget to disconnect local lambda signals — Anonymous lambdas connected to global signals can cause memory leaks if the capturing object is freed.
- NEVER use large textures without VRAM compression — VRAM is limited. Use S3TC/BPTC for desktop (DirectX/Vulkan) and ETC2 for mobile. Note: Disable compression for Pixel Art to avoid artifacts [13].
- NEVER perform tree modifications during physics steps — Adding/removing nodes during
_inter_rayor_physics_processcan lock the physics server. Usecall_deferred. - NEVER skip shader pre-warming in the Compatibility renderer — Unlike Forward+, OpenGL lacks Ubershaders. Pre-instantiate every mesh/VFX in front of the camera for 1 frame behind a loading screen to avoid hitches [21].
Debug → Profiler (F3)
Tabs:
- Time: Function call times
- Memory: RAM usage
- Network: RPCs, bandwidth
- Physics: Collision checks
Profiler-Tab Decision Tree
Open Debug → Profiler first. MANDATORY load only the script for the hot tab/symptom.
Do NOT Load every perf script for a single hitch.
| Profiler / symptom | Likely cause | Script |
|---|---|---|
| Time — same script hot | Alloc / get_node / process | object_pool_system.gd, cache @onready; custom_monitor_profiler.gd |
| Time — off-screen AI/VFX | Process while invisible | MANDATORY manual_culling_logic.gd |
| Memory — climbs over time | Leaks / unique resources | shared_resource_strategy.gd; pair with debugging orphan tools |
| Physics — collision spikes | Query/node RayCast spam | MANDATORY low_level_physics_query.gd |
| GPU / draw calls | Unique sprites/meshes | MANDATORY multimesh_optimizer.gd / multimesh_foliage_manager.gd / texture_array_batching.gd |
| SceneTree overhead at scale | Canvas/mesh item spam | MANDATORY rendering_server_direct.gd |
| Main-thread hitch (gen/parse) | Sync heavy work | MANDATORY worker_thread_pool_manager.gd |
| Crowd path spikes | Nav agents same frame | navigation_agent_optimization.gd |
| Custom game metrics | Missing monitors | custom_performance_monitor.gd |
Available Scripts
object_pool_system.gd
MANDATORY for hot-path spawn/despawn — reuse, do not invent Array pop pools inline.
manual_culling_logic.gd
VisibilityNotifier-driven process disable for CPU-heavy off-screen entities.
rendering_server_direct.gd
RenderingServer canvas/mesh path when SceneTree overhead dominates.
low_level_physics_query.gd
Direct space-state queries vs hundreds of RayCast nodes.
worker_thread_pool_manager.gd
WorkerThreadPool offload for heavy jobs.
multimesh_optimizer.gd / multimesh_foliage_manager.gd
Hardware instancing for dense meshes/foliage.
texture_array_batching.gd
Texture2DArray batching to cut material switches.
shared_resource_strategy.gd
Shared vs local-to-scene memory tradeoffs.
navigation_agent_optimization.gd
Staggered path updates for crowds.
custom_monitor_profiler.gd / custom_performance_monitor.gd
Performance.get_monitor / custom monitors for game-specific spikes.
Expert Pointers (keep short)
- Compatibility renderer: pre-warm pipelines (hidden camera + unique meshes/materials one frame). Forward+/Mobile: Ubershaders still need instantiate-once detection.
- VRAM: S3TC/BPTC desktop, ETC2 mobile; skip compression for pixel art.
- AStar/path budgets belong in navigation_agent_optimization.gd — do not paste thrashy queue snippets as the golden path.
Deep dives (on demand)
- Path time-slicing, Compatibility shader pre-warm, VRAM codec table → profiler-budgets-and-prewarm.md
Reference
Progressive disclosure: open Official Documentation links only when researching a specific API; load Related Skills when routing to a peer domain — do not preload the whole lattice.
Official Documentation
- General optimization — profiler-first workflow so you measure Time/Memory/Physics before changing code.
- CPU optimization — process cost, node lookups, allocations, and why hot-path patterns dominate frame time.
- GPU optimization — draw calls, overdraw, and VRAM compression choices that cut render cost.
- Using MultiMesh — hardware instancing for thousands of meshes and why spatial splits restore culling.
- Using Servers and Resources — RenderingServer/PhysicsServer direct APIs when SceneTree overhead is the bottleneck.
- Using multiple threads — WorkerThreadPool task model for heavy work off the main thread.
- Thread-safe APIs — which engine APIs are safe from worker tasks versus SceneTree-only calls.
- Pipeline compilations — shader/pipeline hitch causes and pre-warm strategies per renderer.
- Optimizing 3D performance — LOD, cull distances, and mesh complexity budgets for 3D scenes.
- Occlusion culling — OccluderInstance3D tradeoffs when frustum culling alone is not enough.
- Performance — built-in monitors plus custom metrics for game-specific bottleneck dashboards.
- Optimizing Navigation Performance — agent update budgets and bake costs for large crowds.
Related Skills
Prerequisites
- godot-project-foundations — scene tree, resources, and import basics required before profiling or pooling patterns make sense.
- godot-gdscript-mastery — typed hot paths, callables, and @onready caching that keep optimization scripts correct.
- godot-resource-data-patterns — shared vs local-to-scene resource ownership that drives memory and unique-instance tradeoffs.
Complements
- godot-2d-physics — collision layers, queries, and body counts that show up as Physics profiler spikes.
- godot-physics-3d — 3D shape cost and RigidBody budgets when optimizing simulation-heavy scenes.
- godot-raycasting-queries — direct space-state query patterns that replace heavy RayCast node stacks.
- godot-shaders-basics — material/shader complexity and Texture2DArray batching that reduce GPU state changes.
- godot-scene-management — threaded loads and scene packing that prevent hitch spikes during streaming.
- godot-navigation-pathfinding — agent path budgets and async bake that pair with staggered AI updates.
- godot-3d-world-building — GridMap/LOD/occlusion level layout that sets the ceiling for draw-call budgets.
Downstream / consumers
- godot-adapt-desktop-to-mobile — resolution/shader fallbacks and battery modes that apply these budgets on weaker GPUs.
- godot-export-builds — export presets and renderer choices where compression and Compatibility pre-warm matter.
- godot-genre-open-world — chunk streaming and HLOD systems that consume MultiMesh, culling, and thread-pool patterns at scale.
Master
- godot-master — library router and mirrored module entry for cross-skill discovery.