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.