2D Map and Scene Generator
0x0funky/agent-sprite-forge
Plans and builds 2D game maps and scenes, from tilemaps and parallax backgrounds to HD-2D plates, with collision checks, a playable HTML preview and Tiled, Godot or LDtk export.
Diagnose frame-rate bottlenecks (CPU vs GPU bound FIRST), control Unreal Insights traces, sample live frame times, and annotate performance captures.
$ npx skills add kevinpbuckley/VibeUE --skill profiling -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install kevinpbuckley/VibeUE profiling --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/kevinpbuckley/VibeUE.git skills-src && mkdir -p .claude/skills && cp -r skills-src/Content/Skills/profiling .claude/skills/profiling && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "profiling" agent skill from https://github.com/kevinpbuckley/VibeUE/tree/master/Content/Skills/profiling into .claude/skills/profiling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "profiling", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/kevinpbuckley/VibeUE/tree/master/Content/Skills/profilingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add kevinpbuckley/VibeUE --skill profiling -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install kevinpbuckley/VibeUE profiling --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/kevinpbuckley/VibeUE.git skills-src && mkdir -p .agents/skills && cp -r skills-src/Content/Skills/profiling .agents/skills/profiling && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "profiling" agent skill from https://github.com/kevinpbuckley/VibeUE/tree/master/Content/Skills/profiling into .agents/skills/profiling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "profiling", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add kevinpbuckley/VibeUE --skill profiling -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install kevinpbuckley/VibeUE profiling --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/kevinpbuckley/VibeUE.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/Content/Skills/profiling .cursor/skills/profiling && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "profiling" agent skill from https://github.com/kevinpbuckley/VibeUE/tree/master/Content/Skills/profiling into .cursor/skills/profiling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "profiling", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/kevinpbuckley/VibeUE.git --path Content/Skills/profiling--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add kevinpbuckley/VibeUE --skill profiling -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install kevinpbuckley/VibeUE profiling --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/kevinpbuckley/VibeUE.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/Content/Skills/profiling .gemini/skills/profiling && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "profiling" agent skill from https://github.com/kevinpbuckley/VibeUE/tree/master/Content/Skills/profiling into .gemini/skills/profiling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "profiling", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install kevinpbuckley/VibeUE profilingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add kevinpbuckley/VibeUE --skill profiling -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/kevinpbuckley/VibeUE.git skills-src && mkdir -p .github/skills && cp -r skills-src/Content/Skills/profiling .github/skills/profiling && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "profiling" agent skill from https://github.com/kevinpbuckley/VibeUE/tree/master/Content/Skills/profiling into .github/skills/profiling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "profiling", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add kevinpbuckley/VibeUE --skill profiling -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install kevinpbuckley/VibeUE profiling --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/kevinpbuckley/VibeUE.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/Content/Skills/profiling .opencode/skills/profiling && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "profiling" agent skill from https://github.com/kevinpbuckley/VibeUE/tree/master/Content/Skills/profiling into .opencode/skills/profiling/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "profiling", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
profilingDiagnose frame-rate bottlenecks (CPU vs GPU bound FIRST), control Unreal Insights traces, sample live frame times, and annotate performance captures.
Profiling is an agent skill from kevinpbuckley/VibeUE. Diagnose frame-rate bottlenecks (CPU vs GPU bound FIRST), control Unreal Insights traces, sample live frame times, and annotate performance captures. Use when FPS is low/bad, the game is slow, or you need to find what is limiting the frame rate.
Its SKILL.md is about 4.5k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Game Development, covering Game development. It works with Python. The repository describes itself as: Unreal Engine Vibe Coding tool. The licence is MIT.
3 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit dc051be. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are python).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Profiling loads about 4.5k tokens when it runs. Until then it costs about 64 tokens; SKILL.md has 1,808 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from kevinpbuckley/VibeUE at commit dc051be, republished under its MIT licence (© kevinpbuckley). 1,808 words, ~4,496 tokens.
.claude/skills/profiling/SKILL.md (or your agent's skills folder).Unreal 5.8's native toolsets have no performance or tracing tools, so this is VibeUE's net-new
capability: unreal.PerformanceService answers "are we CPU- or GPU-bound?" and drives Unreal
Insights captures from Python with no C++ required. Run everything here through execute_python_code.
The whole API is small — read the live signatures once with
discover_python_class(class_name="unreal.PerformanceService"):
| Method | Purpose |
|---|---|
frame_timing(target_fps=60.0) | Game/Render/GPU/RHI thread ms + a CPU-vs-GPU bound verdict + a hint, plus a per-thread budget breakdown gated against target_fps (budget.meets_target PASS/FAIL). Run FIRST. |
force_hitch(thread="game", ms=250.0, frames=1) | Validation helper — deliberately stall a KNOWN thread ("game"/"render"/"both"/"gpu") to confirm the verdict fires. CPU paths are self-measuring: validate from the SAME response (observed_peak_*_ms, verdict_matched_expect) — do NOT follow up with frame_timing. Only the async gpu path is read back on a following frame. Clamped (≤5000 ms, ~10 s total) for safety. |
report(title=..., source="both", file="") | Write a self-contained, shareable HTML report (live verdict + budget + analyse stats + a data-driven "fix in this order" list) to Saved/VibeUE/Performance/report_<timestamp>.html. |
start_pie() / stop_pie() | In-process PIE so frame_timing/force_hitch read a live game world (PIE starts on the next tick — read on a following frame, pie_running flips true). Quick checks only; prefer start_standalone when the numbers must be trusted. |
start_trace(name="mcp_capture", channels="") | Start an Insights trace to file (default channel set if channels empty). |
stop_trace() | Stop the active trace; returns the trace file path + size. |
get_trace_status() | Whether a trace is active and which channels are enabled. |
bookmark(name) | Drop a point-in-time bookmark in the active trace. |
region_start(name) / region_end(name) | Begin / end a named region span in the active trace. |
analyse(source="both", file="") | Read back trace and/or log → frame stats, worst frames, hitches, notable log lines. Combined analysis reports complete, partial, or failed; partial is never top-level success. |
start_standalone(name="standalone_capture", channels="") | Request a separate process with a unique direct-to-file trace. The first response is start_pending; poll status for verified capture. |
stop_standalone() | Gracefully stop the exact tracked process and verify the exact trace finalized; forced/partial outcomes are explicit failures. |
get_standalone_status() | Session ID, PID, map, exact trace/log destinations, process state, and capture/finalization verification. |
All methods return a JSON string. For a representative reading, profile under PIE or a standalone
session (start_standalone), not the bare editor viewport.
Never optimise before you know which processor is the bottleneck. The frame time is
roughly max(GameThread, RenderThread, GPU) — these run in parallel, so only the longest
one sets your FPS. Cutting GPU cost (shadows, Lumen, post-process) does nothing if the
frame is actually game-thread or render-thread bound, and vice-versa. Getting this wrong
wastes the whole session.
import unreal, json
result = json.loads(unreal.PerformanceService.frame_timing())
print(result) # game_thread_ms, render_thread_ms, gpu_ms, rhi_thread_ms, frame_ms, bound, hintStart PIE first (see the pie-testing skill) and park in a representative/worst spot, then call it.
It returns game_thread_ms, render_thread_ms, gpu_ms, rhi_thread_ms, the frame_ms, a bound
verdict (GameThread / RenderThread / GPU), and a hint with what to do next. This is the same
data the stat unit overlay shows, read straight from engine globals — no screenshots, no trace
parsing.
FPS is just 1000 / frame_ms. Because the threads run in parallel, every thread
(GameThread, RenderThread, GPU) must individually finish inside the budget below — the
slowest one alone sets your FPS. A 12 ms GPU is wasted if the game thread takes 25 ms: you
still get ~40 FPS.
| Target FPS | Per-frame budget | Meaning |
|---|---|---|
| 30 FPS | 33.33 ms | Maximum allowable time per frame |
| 60 FPS | 16.66 ms | Maximum allowable time per frame |
| 120 FPS | 8.33 ms | Maximum allowable time per frame |
| 240 FPS | 4.16 ms | Maximum allowable time per frame |
| 360 FPS | 2.77 ms | Maximum allowable time per frame |
Read frame_timing() against this table: if game_thread_ms = 25, you are hard-capped at
~40 FPS no matter what you do to the GPU. To hit 60 FPS the game thread must drop under
16.66 ms; to hit 120 FPS, under 8.33 ms. Always state the bottleneck thread's ms next to the
target budget so the gap is explicit (e.g. "game thread 25 ms vs 16.66 ms for 60 FPS → must
cut 8.3 ms on the game thread").
You don't have to do this arithmetic yourself: frame_timing(target_fps=...) returns the gate —
the budget block carries each thread's headroom / over_budget against the per-frame budget and
a single budget.meets_target PASS/FAIL you can assert on (CI-style perf checks included). To
prove the verdict logic works against a known ground truth, use force_hitch (see the API table).
r.* console variables almost exclusively move GPU and RenderThread cost (Lumen,
shadows, reflections, resolution, draw setup). There is no CVar that makes your Tick,
AI, or animation logic cheaper. When bound == GameThread, the fix lives in code and
Blueprints, driven by what the profiler shows:
Profiler symptom (stat dumpframe -root=gamethread) | Fix lives in | Typical change |
|---|---|---|
High FTickFunctionTask / many ticking actors | C++ / Blueprint | Throttle PrimaryActorTick.TickInterval, disable tick when idle/far, event-drive instead of polling every frame |
High AnimGameThreadTime / many skeletal meshes | C++ / mesh setup | Enable URO (bEnableUpdateRateOptimizations), VisibilityBasedAnimTickOption = OnlyTickPoseWhenRendered |
Expensive Blueprint ReceiveTick | Blueprint graph | Move per-frame logic to timers/events, cache results, early-out |
CharacterMovement / physics / AI heavy | C++ / config | Significance-based LOD, fewer simulated bodies, coarser AI update rate |
Per-frame SetTimer, allocations, logging in hot paths | C++ / Blueprint | Remove redundant work; gate UE_LOG behind a debug flag |
So the workflow for a game-thread bottleneck is: profile → read the offending scope → edit the code/Blueprint that owns it → rebuild → re-profile to confirm. Reaching for CVars here is a category error; they will not move the number.
bound | Meaning | Where to look next |
|---|---|---|
| GameThread | CPU, game thread | Tick / Blueprint / AI / animation. Run stat dumpframe -ms=0.5 -root=gamethread then read the log (LogsToolset). Fix is code/Blueprint, not CVars (see "CVars do NOT fix the game thread" above): throttle ticks, enable anim URO, event-drive logic. Compare the ms to the budget table. |
| RenderThread | CPU, render thread | Draw calls & primitives, dynamic shadow-casting lights. Check stat scenerendering. Instance/merge meshes, enable Nanite, cut dynamic lights. |
| GPU | GPU | Now run ProfileGPU (below). Shadows (VSM), Lumen, translucency, resolution. |
import unreal
w = unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem).get_game_world()
unreal.SystemLibrary.execute_console_command(w, "stat dumpframe -ms=0.5 -root=gamethread")
unreal.SystemLibrary.execute_console_command(w, "stat dumpframe -ms=0.5 -root=renderthread")LogsToolset (tail the main log, ~150 lines) — it prints
the full thread hierarchy in ms (e.g. World Tick Time, FTickFunctionTask, individual
Blueprint ReceiveTick costs). This is the single most useful CPU drill-down.frame_timing(), then r.ScreenPercentage 50, and compare. FPS jumps a lot → GPU-bound.
FPS barely moves → CPU-bound.stat unit is the canonical overlay, but its numbers do not go to the log, and
PIE often runs in a separate window so screenshots are unreliable. Prefer frame_timing()
or methods 1–2 over trying to OCR stat unit.ProfileGPU tells you WHERE GPU time goes, not WHETHER you are GPU-bound. It always
produces a GPU breakdown even on a CPU-bound frame — so reading it first will happily send
you optimising shadows on a frame whose real cost is the game thread. Run STEP 0
(frame_timing()) first; only reach for ProfileGPU once bound == GPU.0b. Never run ProfileGPU (or stat dumpframe) during a trace you intend to average.
Each ProfileGPU stalls the GPU for a full readback (hundreds of ms to seconds), and those
stall frames poison the frame-time stats. Capture clean frame-time traces separately from
GPU/CPU drill-downs.
0c. analyse() reports frame-time aggregates (avg/p95/worst frames, hitches, notable log
lines), not the live CPU/GPU split. Use frame_timing() for the per-thread split.
Profile under PIE or standalone, not the bare editor viewport. The empty editor viewport
is not representative. Start PIE (pie-testing skill) or use start_standalone().
Trace files are large — a ~10 second trace with default channels is 30–50 MB.
Traces land under Saved/Profiling/ (already excluded from source control).
A trace must be active before you bookmark / mark regions. bookmark() and
region_start()/region_end() only do something while get_trace_status() reports a live
trace. Call start_trace() first.
import unreal, json
# Default channel set (frame, cpu, gpu, log, ...) — pass channels="" or omit
res = json.loads(unreal.PerformanceService.start_trace("combat_encounter"))
print(res) # includes the trace file path
# ... reproduce the workload ...
stopped = json.loads(unreal.PerformanceService.stop_trace())
print(stopped) # trace file path + size# Comma-separated channel list (short names accepted by the service)
unreal.PerformanceService.start_trace("mem_capture", "frame,cpu,memalloc,memtag,object,loadtime")import unreal, json
print(json.loads(unreal.PerformanceService.get_trace_status())) # active? which channels?Use these while a trace is active to label interesting moments in the Unreal Insights timeline.
import unreal
# Single point-in-time bookmark (vertical line in Insights)
unreal.PerformanceService.bookmark("spawn_wave_3")
# Named region (coloured span)
unreal.PerformanceService.region_start("loading_level")
# ... trigger the thing you want to measure ...
unreal.PerformanceService.region_end("loading_level")analyse()analyse() reads a finished trace and/or the log and returns a perf summary (frame stats, worst
frames, hitches, notable log lines) without opening Unreal Insights:
import unreal, json
summary = json.loads(unreal.PerformanceService.analyse("both")) # "trace", "logs", or "both"
print(summary) # avg/p95/worst frame ms, hitches, notable log lines
# Analyse a specific file instead of the last trace started/stopped
unreal.PerformanceService.analyse("trace", "Saved/Profiling/combat_encounter.utrace")For source="both", inspect status: complete means both sources succeeded, partial means
exactly one did, and failed means neither did. A partial result deliberately has success=false
and names available_sources / failed_sources; this prevents a missing trace from masquerading as
a successful capture. Log output separates pso_hitch_event_lines, cumulative
pso_hitches_reported, and pso_hitch_summary_lines; repeated cumulative summary lines are not
summed. The backward-compatible pso_hitches field is the best supported count.
Remember: analyse() is frame-time aggregates only — use frame_timing() for the CPU/GPU split.
The editor viewport (and even PIE) is not always representative of a packaged run. start_standalone()
launches the game as a separate standalone process with one unique, direct-to-file trace. It does
not use the global Unreal Trace Server store and never substitutes an unrelated "latest" trace:
import unreal, json
start = json.loads(unreal.PerformanceService.start_standalone("standalone_capture"))
# start is request_accepted=true, success=false, pending=true until the child and trace exist
status = json.loads(unreal.PerformanceService.get_standalone_status())
# poll on later editor ticks until status["capture_verified"] is true
# ... let it run / drive the workload ...
stopped = json.loads(unreal.PerformanceService.stop_standalone())
# require stopped["success"] and status == "finalized" before trusting the traceRecord the returned session_id, pid, map, trace_file, and log_file with benchmark results.
If shutdown is forced or the exact trace stays missing/empty, stop returns failure and may mark the
available log/partial trace as partial; do not silently use another store trace. analyse("both")
can still return a clearly marked log-only partial summary.
For comparisons, keep map/route, resolution, scalability, difficulty, power mode, and warm-up fixed;
disable editor background throttling for unattended runs and restore its prior value afterward.
Treat short or sparse samples as observations, not stable averages. Compare median/p95/p99 and frame
counts above 33/50/100 ms, and separate cold-start/shader/PSO runs from warm-cache runs. Run
ProfileGPU or stat dumpframe separately because their instrumentation stalls contaminate traces.
import unreal, json
# 1. CPU vs GPU verdict FIRST (PIE running, parked in a representative spot)
print(json.loads(unreal.PerformanceService.frame_timing()))
# 2. Capture a clean trace around the workload
unreal.PerformanceService.start_trace("combat_encounter")
unreal.PerformanceService.region_start("wave_spawn")
# (trigger the gameplay here)
unreal.PerformanceService.region_end("wave_spawn")
res = json.loads(unreal.PerformanceService.stop_trace())
print("trace:", res)
# 3. Summarise without leaving Python
print(json.loads(unreal.PerformanceService.analyse("both")))start_trace / start_standalone accept a comma-separated channels string; empty uses the
default set (frame, cpu, gpu, log, …). Common channels:
| Channel | What it captures | Use for |
|---|---|---|
frame | Frame boundaries, wall time | Always include — baseline for everything |
cpu | CPU named scopes | CPU hotspots, Blueprint tick |
gpu | GPU pass timings | GPU bound? Where are draw calls going? |
stats | UE stat counters | Actor/component counts, frame budget |
log | Log output embedded in trace | Correlate log spam with frame spikes |
memalloc | Per-allocation callstacks | Memory churn, GC pressure |
memtag | High-level memory category totals | Which system is eating RAM? |
object | UObject create/destroy | Asset streaming, actor spawning |
niagara | Niagara system tick | Particle perf |
animation | Animation graph evaluation | Anim Blueprint cost |
net | Replication, RPC timing | Multiplayer performance |
slate | UI widget tick and paint | UI overhead |
loadtime | Asset streaming / load events | Load hitches |
Channel naming may vary slightly by build; call
get_trace_status()afterstart_trace()to see the channels actually enabled.
| Investigation | channels string |
|---|---|
| General (balanced) | frame,cpu,gpu,stats,log |
| Memory | frame,memalloc,memtag,object,loadtime |
| Animation / character | frame,cpu,animation,stats |
| UI / Slate | frame,cpu,slate,stats |
| Niagara / VFX | frame,cpu,gpu,niagara |
| Multiplayer | frame,cpu,net,stats |
| Load / streaming | frame,loadtime,object,log |
analyse() covers most needs from Python, but you can open a .utrace for the full timeline UI:
Editor menu: Tools → Run Unreal InsightsOr from the command line:
"<UE install>/Engine/Binaries/Win64/UnrealInsights.exe" "<path>/combat_encounter.utrace"Trace files are written under:
<project root>/Saved/Profiling/<name>.utrace© kevinpbuckley, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in Content/Skills/profiling of kevinpbuckley/VibeUE.
Open the folder on GitHubat commit dc051be
Profiling next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Profiling this skillkevinpbuckley/VibeUE | 717 | — | ~4.5k | Automated safety check: Pass | MIT | |
| 2D Map and Scene Generator0x0funky/agent-sprite-forge | 4.3k | — | ~2.9k | Automated safety check: Pass | MIT | |
| Spine AnimationGenielabsOpenSource/spine-animation-ai | 512 | — | ~17k | Automated safety check: Pass | CC-BY-NC-4.0 | |
| Unreal BridgeTornLux/UnrealBridge | 305 | — | ~8.4k | Automated safety check: Notes | MIT | |
| Text To 3D AssetLaurentiuGabriel/unreal-game-assets-creation-skill | 146 | — | ~2.1k | Automated safety check: Pass | None | |
| Substance 3D Texturingfreshtechbro/claudedesignskills | 986 | — | ~4k | Automated safety check: Pass | MIT |
0x0funky/agent-sprite-forge
Plans and builds 2D game maps and scenes, from tilemaps and parallax backgrounds to HD-2D plates, with collision checks, a playable HTML preview and Tiled, Godot or LDtk export.
GenielabsOpenSource/spine-animation-ai
Create Spine 2D skeletal animations from pre-existing character assets (separated body-part PNGs, atlas spritesheet, or a full character image).
TornLux/UnrealBridge
Execute Python scripts inside a running Unreal Engine 5.3+ editor via TCP bridge.
LaurentiuGabriel/unreal-game-assets-creation-skill
Generate a game-ready 3D asset by running the local AI pipeline sequentially: Fooocus (SDXL text-to-image) - Hunyuan3D-2 (image-to-textured-GLB) - optional Blender FBX convert + Unreal import.
freshtechbro/claudedesignskills
Comprehensive skill for Adobe Substance 3D Painter texturing and material creation workflow.
scenario-labs/skills
A skill your agent uses when writing or fixing Maya pipeline code in Python: mayapy batch jobs over many scenes, validating and auto-fixing scenes, FBX export for Unreal or Unity (static, skeletal…
kevinpbuckley/VibeUE
Previews, validates and bakes bone-rotation edits on Unreal Engine AnimSequences, enforcing a coordinate space and a constraint-checked preview-validate-bake loop.
kevinpbuckley/VibeUE
Creates and edits Unreal Engine Animation Montages through AnimMontageService: sections, slots, segments, branching points, notifies and blend settings.
kevinpbuckley/VibeUE
Creates and edits AnimSequence keyframes and bone tracks in Unreal Engine through AnimSequenceService, following an inspect, preview, validate and bake workflow with correct bone-space handling.
kevinpbuckley/VibeUE
Imports files into Unreal Engine, exports textures, reads the Content Browser selection and checks open assets via VibeUE, plus mesh reimport material fixes.
kevinpbuckley/VibeUE
Changes Unreal Engine console variables, scalability levels and raw INI values through VibeUE's Python API, now that registered settings moved to the engine's own toolset.
kevinpbuckley/VibeUE
Creates and wires Unreal Engine Enhanced Input assets through VibeUE's InputService: Input Actions, Mapping Contexts, key bindings, triggers and modifiers.
Works with
Categories
Diagnose frame-rate bottlenecks (CPU vs GPU bound FIRST), control Unreal Insights traces, sample live frame times, and annotate performance captures. Profiling is an agent skill from kevinpbuckley/VibeUE. Diagnose frame-rate bottlenecks (CPU vs GPU bound FIRST), control Unreal Insights traces, sample live frame times, and annotate performance captures.
Profiling fits situations like: the game is slow; you need to find what is limiting the frame rate.
Run `npx skills add kevinpbuckley/VibeUE --skill profiling -a claude-code`. Or copy the skill folder (Content/Skills/profiling in kevinpbuckley/VibeUE) into .claude/skills/profiling in your project. Claude Code loads it when a task matches its description.
Run `npx skills add kevinpbuckley/VibeUE --skill profiling -a codex`. Or copy the skill folder (Content/Skills/profiling in kevinpbuckley/VibeUE) into .agents/skills/profiling in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add kevinpbuckley/VibeUE --skill profiling -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/profiling, .gemini/skills/profiling, .github/skills/profiling and .opencode/skills/profiling in your project.
SKILL.md names no scripts, command-line tools or credentials: Profiling is instructions for the agent only. Our summary lists: Python 3.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Profiling is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.5k tokens (SKILL.md is roughly 18k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Profiling: 2D Map and Scene Generator (0x0funky/agent-sprite-forge, 4.3k stars), Spine Animation (GenielabsOpenSource/spine-animation-ai, 512 stars), Unreal Bridge (TornLux/UnrealBridge, 305 stars) and Text To 3D Asset (LaurentiuGabriel/unreal-game-assets-creation-skill, 146 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
kevinpbuckley (a GitHub user) maintains it in kevinpbuckley/VibeUE, which has 717 GitHub stars. The repository holds 39 skills in this directory. The repository was last updated on October 1, 2026.
Source: kevinpbuckley/VibeUE on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.