SuperAPI AI Directory

godot-performance-optimization

Coding & development

View repository

Updated 10-15 18:28

About this skill

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

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

Related Skills

Prerequisites

Complements

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.