ai-behavior-trees-util…
Build a production behavior-tree runtime (Blackboard, action/condition leaves, sequence/selector/parallel composites, decorators)…
Find and fix game performance problems methodically — measure with the engine profiler first, reason about the frame-time budget, locate the CPU-vs-GPU bottleneck, then apply the right fix: object pooling, draw-call batching, fewer allocations/GC spikes, and asset budgets.
Claude Code
$ npx -y skills add gamedev-skills/awesome-gamedev-agent-skills --skill performance-optimization --agent claude-code
Codex
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill performance-optimization -a codex -y
Cursor
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill performance-optimization -a cursor -y
Gemini CLI
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill performance-optimization -a gemini-cli -y
GitHub Copilot
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill performance-optimization -a github-copilot -y
OpenCode
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill performance-optimization -a opencode -y
Windsurf
$ npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill performance-optimization -a windsurf -y
name: performance-optimization description: > Finds and fixes game frame-rate problems by measurement in Godot, Unity, Unreal or Roblox: CPU- vs GPU-bound, then the biggest fix (draw calls, pooling, GC spikes). Use for low FPS, stutter, a first-use hitch, or requests to optimize or profile. Not for build size (`unity-build-size`), physics jitter (`physics-tuning`) or network lag (`roblox-networking`, `godot-multiplayer`).
The loop: **set a budget, measure, find the one bottleneck, fix it, measure again, report the numbers.** Guesses usually target the wrong system, so nothing changes until a profiler or a frame-time capture says where the time goes. This skill is the cross-engine method and the fixes that recur; each engine's profiler is listed below and in the reference.
**Not this skill:** physics stability (`physics-tuning`), install or download size (`unity-build-size`), network latency (`roblox-networking`, `godot-multiplayer`), shader maths (`shader-programming`).
1. **Turn the complaint into a number.** Target FPS gives the budget: 60 FPS is 16.67 ms, 30 is 33.3 ms, 120 is 8.33 ms. Find a repeatable worst-case scene and save it (a test level, a recorded input, a fixed seed). 2. **Uncap before measuring.** VSync and frame caps hide headroom: a 4 ms frame and a 15 ms frame both show 60 FPS. Godot `--disable-vsync` (and `--max-fps 0`); Unity `QualitySettings.vSyncCount = 0` with `Application.targetFrameRate = -1` on desktop; Unreal `r.VSync 0` and `t.MaxFPS 0`. Then read frame time in ms, not FPS. 3. **Profile a release-like build on target hardware.** Editor and debug builds add overhead and skip compiler optimization; use a Godot release export, a Unity Development build with the profiler attached, or an Unreal Development or Test build. 4. **Split CPU from GPU.** Compare main-thread, render-thread and GPU time. The side closest to the frame time is the bottleneck; fixing the other side changes nothing. 5. **Fix the single biggest cost**, preferring doing less work (cache, partition space, run less often) over polishing a hot line. Then apply the matching fix below. 6. **Re-measure the same scene on the same machine**, three runs each, and keep or revert on the numbers. 7. **Set budgets** per subsystem and per asset so the fix stays fixed, and add the frame-time check to CI where the engine allows it. 8. **Report** the scene, hardware, build type, before and after (average and p95 or p99 frame time), the bottleneck and the fix. Say what was measured headless or in the editor and what still needs the user's device.
@60 FPS = 16.67 ms. The slower of CPU frame and GPU frame sets the frame rate. Example sub-budgets: gameplay/scripts ~5 ms · physics ~3 ms · render submit ~4 ms · UI ~2 ms · slack. Mobile: keep 20-30% headroom so the game survives thermal throttling.
Godot 4.7 : Debugger > Profiler (script and physics), Visual Profiler (CPU vs GPU render time
per pass), Monitors (FPS, draw calls, memory, pipeline compilations).
Performance.get_monitor(TIME_PROCESS) is the worst frame of the last second in
SECONDS, refreshed once a second; time frames yourself for per-frame spikes.
Unity 6.3 LTS : Profiler window + Frame Debugger. ProfilerRecorder on "CPU Main Thread Frame Time"
and "GPU Frame Time" (release players need Frame Timing Stats in Player Settings).
Unreal 5.8 : stat unit (Frame / Game / Draw / RHIT / GPU), stat scenerendering (draw calls),
Unreal Insights; `csvprofile frames=600` writes a CSV capture you can read.
Roblox : MicroProfiler (Ctrl+F6 in Studio and the desktop client; mobile via its web UI).
# Game and Draw are CPU threads; GPU is the graphics card. Whichever is nearest Frame wins.**Roblox:** profile on a mid-range phone, because a capped desktop hides the problem. With Studio Assistant, Roblox's built-in `rbx-perf-profiling` (reads MicroProfiler captures) and `rbx-scene-analysis` (rendering cost, memory, leaked instances) give real data; use `roblox-studio-workflow` to run checks in Studio, `roblox-physics` for assembly and simulation cost, and `roblox-networking` when "lag" means network delay rather than frame time.
# tools/frame_stats.gd: CPU frame time of one scene, headless (no GPU work is measured).
# godot --headless --path . --script res://tools/frame_stats.gd -- res://levels/worst.tscn 600 16.6
extends SceneTree
func _initialize() -> void:
var args := OS.get_cmdline_user_args()
var scene_path := args[0] if args.size() > 0 else "res://main.tscn"
var frames := int(args[1]) if args.size() > 1 else 600
var budget_ms := float(args[2]) if args.size() > 2 else 16.6
OS.low_processor_usage_mode_sleep_usec = 0 # headless otherwise sleeps ~6.9 ms a frame
root.add_child(load(scene_path).instantiate())
for i in 60: # skip loading and first-use spikes
await process_frame
var ms := PackedFloat64Array()
var last := Time.get_ticks_usec()
for i in frames:
await process_frame
var now := Time.get_ticks_usec()
ms.append((now - last) / 1000.0) # whole frame: scripts, physics, engine
last = now
ms.sort()
var avg := 0.0
for v in ms:
avg += v / ms.size()
var p95 := ms[int(ms.size() * 0.95)]
var p99 := ms[int(ms.size() * 0.99)]
var over := ms.size() - ms.bsearch(budget_ms, false)<img src="docs/assets/awesome-gamedev-agent-skills-banner.png" width="820" alt="awesome-gamedev-agent-skills — game-dev skills for AI coding agents.
Build a production behavior-tree runtime (Blackboard, action/condition leaves, sequence/selector/parallel composites, decorators)…
Implement game audio practice — bus/mixer architecture and gain in decibels, ducking (sidechain), adaptive/dynamic music via…
Build game cameras that feel good — 2D follow with a deadzone, look-ahead, smoothing, and level-bounds clamping; 3D third-person…
Plan, generate, source, normalize, and validate cohesive visual game assets. Use for art direction, style bibles, sprites,…
Build branching dialogue and narrative — a node/choice graph with conditions, variables, and localization hooks — and choose…
Design NPC and enemy decision-making with finite state machines, behavior trees, steering behaviors, and A* pathfinding —…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.