--- name: godot-performance-optimization description: "Expert blueprint for performance profiling and optimization (frame drops, memory leaks, draw calls) using Godot Profiler, object pooling, visibility culling, and bottleneck identification. Use when diagnosing lag, optimizing for target FPS, or reducing memory usage. Keywords profiling, Godot Profiler, bottleneck, object pooling, VisibleOnScreenNotifier, draw calls, MultiMesh." --- # Performance Optimization Profiler-driven analysis, object pooling, and visibility culling define optimized game performance. ## Available Scripts ### [worker_thread_pool_manager.gd](scripts/worker_thread_pool_manager.gd) Expert logic for offloading heavy computation to Godot 4's WorkerThreadPool for multi-threaded processing. ### [object_pool_system.gd](scripts/object_pool_system.gd) Minimal allocation strategy using node visibility and process toggling instead of constant instantiation. ### [rendering_server_direct.gd](scripts/rendering_server_direct.gd) Bypassing the SceneTree logic for massive canvas item rendering directly via the RenderingServer. ### [low_level_physics_query.gd](scripts/low_level_physics_query.gd) High-performance direct physics space state queries, faster than using RayCast nodes for hundreds of checks. ### [custom_monitor_profiler.gd](scripts/custom_monitor_profiler.gd) Implementation of real-time performance monitoring using Performance.get_monitor() for bottleneck detection. ### [manual_culling_logic.gd](scripts/manual_culling_logic.gd) Disabling off-screen logic manually using VisibilityNotifiers to cull CPU-heavy processing. ### [shared_resource_strategy.gd](scripts/shared_resource_strategy.gd) Expert management of Local-to-Scene vs Shared resources to balance memory usage and unique instance states. ### [texture_array_batching.gd](scripts/texture_array_batching.gd) Reducing draw calls and state changes by utilizing TextureArrays for multi-item shader-based batching. ### [multimesh_optimizer.gd](scripts/multimesh_optimizer.gd) Rendering thousands of animated mesh instances via hardware instancing (MultiMeshInstance3D). ### [navigation_agent_optimization.gd](scripts/navigation_agent_optimization.gd) Staggered path update strategy for massive AI crowds to prevent pathfinding bottlenecks in a single frame. ## 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_ignore` or conditional `if OS.is_debug_build():` [21]. - **NEVER ignore `VisibleOnScreenNotifier2D` for off-screen entities** — Enemies processing logic off-screen = wasted CPU. Disable `set_process(false)` when `screen_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()`** — Calling `get_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. Use `WorkerThreadPool` to 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_ray` or `_physics_process` can lock the physics server. Use `call_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 ## Common Optimizations ### Object Pooling ```gdscript var bullet_pool: Array[Node] = [] func get_bullet() -> Node: if bullet_pool.is_empty(): return Bullet.new() return bullet_pool.pop_back() func return_bullet(bullet: Node) -> void: bullet.hide() bullet_pool.append(bullet) ``` ### Visibility Notifier ```gdscript # Add VisibleOnScreenNotifier2D # Disable processing when off-screen func _on_screen_exited() -> void: set_process(false) func _on_screen_entered() -> void: set_process(true) ``` ### AStar-Throttler (Pathfinding Budget) Spreading pathfinding costs over multiple frames to prevent frame-time spikes. - **Implementation**: ```gdscript var _query_queue: Array[Callable] = [] const TIME_BUDGET_USEC := 1000 # 1ms budget func _process(_delta): var start_time := Time.get_ticks_usec() while not _query_queue.is_empty() and (Time.get_ticks_usec() - start_time) < TIME_BUDGET_USEC: var query = _query_queue.pop_front() query.call() ``` ### Shader-Preloading (Zero-Hitch Strategy) - **Forward+ / Mobile**: Godot 4.4+ uses **Ubershaders** for automatic precompilation. Ensure scenes are instantiated at least once (even if invisible) at load-time to trigger pipeline detection [19]. - **Compatibility (OpenGL)**: Place a hidden `Camera3D` looking at a small area containing every unique mesh and material in your project for 1 frame during the loading screen [20]. ### VRAM Compression Guide - **S3TC (Desktop)**: Best for high-quality textures on Windows/Linux/macOS. - **BPTC (Desktop)**: Superior quality for HDR and normal maps; slightly higher VRAM usage. - **ETC2 (Mobile)**: The standard for Android/iOS; ensure textures are opaque where possible for maximum compatibility [13]. ## Reference - [Godot Docs: Performance Optimization](https://docs.godotengine.org/en/stable/tutorials/performance/general_optimization.html) ### Related - Master Skill: [godot-master](../godot-master/SKILL.md)