Debugging Code
JetBrains/skills
A skill your agent uses for debugger-driven runtime root-cause analysis in Rider-supported solutions and projects, including .NET/C, F, VB, C++, Unity, Unreal Engine, and other GameDev or…
A skill your agent uses when writing or running Unreal Engine tests, adding logging, or profiling a build.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-testing-debugging -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-testing-debugging --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/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/ue-testing-debugging .claude/skills/ue-testing-debugging && 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 "ue-testing-debugging" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-testing-debugging into .claude/skills/ue-testing-debugging/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-testing-debugging", 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/quodsoler/unreal-engine-skills/tree/main/skills/ue-testing-debuggingType 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 quodsoler/unreal-engine-skills --skill ue-testing-debugging -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-testing-debugging --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/ue-testing-debugging .agents/skills/ue-testing-debugging && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "ue-testing-debugging" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-testing-debugging into .agents/skills/ue-testing-debugging/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-testing-debugging", 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 quodsoler/unreal-engine-skills --skill ue-testing-debugging -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-testing-debugging --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/ue-testing-debugging .cursor/skills/ue-testing-debugging && 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 "ue-testing-debugging" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-testing-debugging into .cursor/skills/ue-testing-debugging/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-testing-debugging", 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/quodsoler/unreal-engine-skills.git --path skills/ue-testing-debugging--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 quodsoler/unreal-engine-skills --skill ue-testing-debugging -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-testing-debugging --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/ue-testing-debugging .gemini/skills/ue-testing-debugging && 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 "ue-testing-debugging" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-testing-debugging into .gemini/skills/ue-testing-debugging/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-testing-debugging", 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 quodsoler/unreal-engine-skills ue-testing-debuggingInstalls 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 quodsoler/unreal-engine-skills --skill ue-testing-debugging -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/ue-testing-debugging .github/skills/ue-testing-debugging && 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 "ue-testing-debugging" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-testing-debugging into .github/skills/ue-testing-debugging/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-testing-debugging", 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 quodsoler/unreal-engine-skills --skill ue-testing-debugging -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-testing-debugging --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/ue-testing-debugging .opencode/skills/ue-testing-debugging && 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 "ue-testing-debugging" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-testing-debugging into .opencode/skills/ue-testing-debugging/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-testing-debugging", 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.
ue-testing-debuggingA skill your agent uses when writing or running Unreal Engine tests, adding logging, or profiling a build.
Ue Testing Debugging is an agent skill from quodsoler/unreal-engine-skills. Use when writing or running Unreal Engine tests, adding logging, or profiling a build. Also use when the user mentions 'UELOG', 'log category', 'DEFINELOGCATEGORY', 'UELOGFMT', 'verbosity', 'check', 'ensure', 'ensureMsgf', 'verify', 'IMPLEMENTSIMPLEAUTOMATIONTEST', 'automation test', 'TESTCLASS', 'CQTest', 'AFunctionalTest', 'latent command', 'Unreal Insights', 'TRACECPUPROFILEREVENTSCOPE', 'TRACEBOOKMARK', 'stat unit', 'SCOPECYCLECOUNTER', 'memreport', 'DrawDebugLine', 'UEVLOG', 'gameplay debugger', 'ShowDebug'…
Its SKILL.md is about 8.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 3 other files, including reference files (for example `references/automation-test-patterns.md` and `references/profiling-commands.md`).
It sits in Game Development, covering Game development and Debugging. It works with Unreal Engine. The repository describes itself as: Unreal Engine C++ skills for AI coding agents. 27 skills covering gameplay, rendering, networking, animation, and more. Works with Claude Code, Cursor, Windsurf, and any agent… The licence is MIT.
Read from SKILL.md and the folder at commit f3742d7. 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 cpp).
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.
Ue Testing Debugging loads about 8.1k tokens when it runs, and up to ~17k if it reads all its reference files. Until then it costs about 178 tokens; SKILL.md has 2,121 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 quodsoler/unreal-engine-skills at commit f3742d7, republished under its MIT licence (© quodsoler). 2,121 words, ~8,136 tokens.
.claude/skills/ue-testing-debugging/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.Target engine: UE 5.8. APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".
This skill owns logging, assertions, automation/functional testing, console commands and performance profiling for the repo. Logging, assertions, stats, trace and CVars live in Core (Logging/, Misc/AssertionMacros.h, Stats/Stats.h, ProfilingDebugging/, HAL/IConsoleManager.h). Debug drawing, the Visual Logger and AHUD::ShowDebug live in Engine. Test frameworks are the developer modules AutomationController, CQTest, FunctionalTesting and AutomationDriver; the Gameplay Debugger is the runtime module GameplayDebugger.
Read .agents/ue-project-context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing. Identify the area from the request and the codebase; ask only when two plausible readings would produce different code.
| Request is about… | Go to |
|---|---|
UE_LOG, categories, verbosity, structured logging | Logging |
check, ensure, verify, crash on bad state | Assertions |
Unit tests, IMPLEMENT_SIMPLE_AUTOMATION_TEST, specs, latent commands | Automation Tests |
TEST_CLASS, ASSERT_THAT, fixture-style tests | CQTest |
Tests placed in a map, AFunctionalTest | Functional Tests |
Insights, stat, cycle counters, CSV, memory, hitches | Profiling |
DrawDebug*, UE_VLOG, Gameplay Debugger, ShowDebug | Debug Visualization |
Exec functions, FAutoConsoleCommand, CVars | Console Commands and CVars |
#include "Logging/LogMacros.h"
// MyGameLogging.h — DECLARE_LOG_CATEGORY_EXTERN(Name, DefaultVerbosity, CompileTimeVerbosity)
DECLARE_LOG_CATEGORY_EXTERN(LogMyGame, Log, All);
DEFINE_LOG_CATEGORY(LogMyGame); // MyGameLogging.cpp| Macro | Where | Scope |
|---|---|---|
DECLARE_LOG_CATEGORY_EXTERN(Name, Default, CompileTime) | header | the module and everything that includes it |
DEFINE_LOG_CATEGORY(Name) | one .cpp | pairs with the EXTERN form |
DEFINE_LOG_CATEGORY_STATIC(Name, Default, CompileTime) | one .cpp | that translation unit only |
DECLARE_LOG_CATEGORY_CLASS(Name, Default, CompileTime) | class body | class static; pair with DEFINE_LOG_CATEGORY_CLASS(Class, Name) |
DefaultVerbosity must be <= CompileTimeVerbosity or the static_assert inside the category macro fires. Anything above CompileTimeVerbosity is deleted by the compiler, so DECLARE_LOG_CATEGORY_EXTERN(LogMyGame, Log, Log) removes every Verbose/VeryVerbose call site. Monolithic builds can cap all categories at once by defining COMPILED_IN_MINIMUM_VERBOSITY.
| Level | Console | File | Notes |
|---|---|---|---|
Fatal | yes | yes | crashes the process, even when logging is disabled |
Error | yes | yes | collected by commandlets and the editor; fails a commandlet |
Warning | yes | yes | can be promoted to an error |
Display | yes | yes | use this when the user must see the line |
Log | no | yes | file only — the default for development messages |
Verbose | no | yes | only once the category is raised to Verbose |
VeryVerbose | no | yes | only once the category is raised to VeryVerbose |
ELogVerbosity::All is an alias for VeryVerbose and is the usual CompileTimeVerbosity argument.
UE_LOG(LogMyGame, Display, TEXT("Player %s spawned"), *PlayerName);
UE_LOG(LogMyGame, Warning, TEXT("Inventory full, dropped %s"), *ItemName);
UE_LOG(LogMyGame, Error, TEXT("Failed to load asset %s"), *AssetPath);
UE_LOG(LogMyGame, Fatal, TEXT("Save data unrecoverable")); // crashes
// Condition and arguments are evaluated only when the category is active.
UE_CLOG(Health <= 0.f, LogMyGame, Warning, TEXT("%s has zero health"), *GetName());Wrap an expensive report in if (UE_LOG_ACTIVE(LogMyGame, Verbose)) { … } so the work itself is skipped, not just the formatting.
UE_LOGFMT emits named fields that survive into Insights and log analysis; use {Name} placeholders, not %s.
#include "Logging/StructuredLog.h"
// Named fields: order is irrelevant, extra fields are allowed.
UE_LOGFMT(LogMyGame, Warning, "Loading '{Name}' failed with error {Error}",
("Name", AssetName), ("Error", ErrorCode), ("Flags", LoadFlags));
// Positional fields: the values must match the placeholders exactly.
UE_LOGFMT(LogMyGame, Display, "Spawned {Count} actors in {Seconds}s", SpawnCount, Elapsed);
UE_CLOGFMT(bFailed, LogMyGame, Error, "Retry {Attempt} failed", ("Attempt", Attempt));Field names must match [A-Za-z0-9_]+ and be unique per event; values serialize through SerializeForLog or operator<<(FCbWriter&, T). UE_LOGFMT takes at most 16 fields — use UE_LOGFMT_EX with UE_LOGFMT_FIELD / UE_LOGFMT_VALUE beyond that.
NO_LOGGING is !USE_LOGGING_IN_SHIPPING in both Test and Shipping, and 0 in Debug and Development. Under NO_LOGGING, UE_LOG/UE_CLOG/UE_LOGFMT collapse to a Fatal-only path: every non-fatal call disappears, arguments included. Set bUseLoggingInShipping = true; in MyGame.Target.cs to define USE_LOGGING_IN_SHIPPING=1 and get logging back.
-LogCmds="LogMyGame Verbose, LogNet Warning" # command line, applied at boot
Log list [Filter] # every category with its current verbosity
Log LogMyGame Verbose # raise one category
Log global none # silence everything
Log reset # restore defaultsFrom code use UE_SET_LOG_VERBOSITY(LogMyGame, Verbose); from config use [Core.Log] in DefaultEngine.ini.
All in Misc/AssertionMacros.h. Choose by who is wrong: check for programmer error, ensure for a recoverable surprise worth reporting, a plain if for user or data input.
check(Component != nullptr);
checkf(Index >= 0 && Index < Items.Num(), TEXT("Index %d out of [0,%d)"), Index, Items.Num());
checkNoEntry(); // unreachable branch
checkNoReentry(); // must not be entered twice
checkSlow(ValidateExpensiveInvariant()); // Debug only
verify(Manager->Initialize()); // expression ALWAYS evaluated
if (ensure(Component != nullptr))
{
Component->Activate(); // ensure() returns the condition
}
ensureMsgf(Health > 0.f, TEXT("%s has health %.1f"), *GetName(), Health);
ensureAlways(bInitialized); // reports every failure, not just the firstensure/ensureMsgf report once per call site per session; ensureAlways/ensureAlwaysMsgf report every time. All four return the condition, so they compose with if.
| Build | DO_CHECK | DO_ENSURE | DO_GUARD_SLOW | NO_LOGGING |
|---|---|---|---|---|
| Debug | 1 | 1 | 1 | 0 |
| Development | 1 | 1 | 0 | 0 |
| Test and Shipping | USE_CHECKS_IN_SHIPPING | USE_ENSURES_IN_SHIPPING | 0 | !USE_LOGGING_IN_SHIPPING |
USE_CHECKS_IN_SHIPPING defaults to 0 and is set by bUseChecksInShipping in the target rules, so Test builds also strip check and ensure by default. When DO_CHECK is 0, check(expr) degrades to CA_ASSUME(expr) and the expression is never evaluated; verify(expr) still evaluates it and only drops the halt.
Test sources live in a Private/Tests folder of the module under test, or in a dedicated test module. Wrap each test file in #if WITH_DEV_AUTOMATION_TESTS (or WITH_AUTOMATION_TESTS = WITH_DEV_AUTOMATION_TESTS || WITH_PERF_AUTOMATION_TESTS) — the IMPLEMENT_* macros alone still compile the class, they only skip registration when WITH_AUTOMATION_WORKER is 0 (Misc/AutomationTest.h:4366); UBT turns both on for every configuration except Test and Shipping, overridable with bForceCompileDevelopmentAutomationTests, bForceCompilePerformanceAutomationTests and bForceDisableAutomationTests (UEBuildTarget.cs:6309-6325). Module and target wiring, the full pattern library and the command lines for running tests are in references/automation-test-patterns.md.
// Source/MyGame/Private/Tests/MyInventoryTest.cpp — whole file inside #if WITH_DEV_AUTOMATION_TESTS
#include "Misc/AutomationTest.h"
#include "MyInventoryComponent.h"
IMPLEMENT_SIMPLE_AUTOMATION_TEST(FMyInventoryAddTest, "MyGame.Inventory.AddItem",
EAutomationTestFlags::EditorContext | EAutomationTestFlags::ProductFilter)
bool FMyInventoryAddTest::RunTest(const FString& Parameters)
{
UMyInventoryComponent* Inv = NewObject<UMyInventoryComponent>(GetTransientPackage());
UE_RETURN_ON_ERROR(Inv != nullptr, TEXT("Inventory created"));
Inv->AddItem(FName("Sword"), 1);
TestEqual(TEXT("Count after add"), Inv->GetItemCount(FName("Sword")), 1);
TestTrue(TEXT("Has sword"), Inv->HasItem(FName("Sword")));
TestFalse(TEXT("No axe"), Inv->HasItem(FName("Axe")));
return true;
}IMPLEMENT_COMPLEX_AUTOMATION_TEST adds virtual void GetTests(TArray<FString>& OutBeautifiedNames, TArray<FString>& OutTestCommands) const and runs RunTest once per entry. IMPLEMENT_CUSTOM_SIMPLE_AUTOMATION_TEST(TClass, TBaseClass, PrettyName, TFlags) declares a simple test whose base is a shared fixture you derive from FAutomationTestBase.
EAutomationTestFlags is an enum class with ENUM_CLASS_FLAGS, so combine with |. Two static_asserts enforce at least one context flag and exactly one filter flag.
| Group | Values |
|---|---|
| Context (≥1 required) | EditorContext, ClientContext, ServerContext, CommandletContext, ProgramContext |
| Filter (exactly 1) | SmokeFilter, EngineFilter, ProductFilter, PerfFilter, StressFilter, NegativeFilter |
| Priority | CriticalPriority, HighPriority, MediumPriority, LowPriority |
| Other | NonNullRHI, RequiresUser, Disabled, SupportsAutoRTFM |
EAutomationTestFlags_ApplicationContextMask covers every context flag in one token.
TestEqual(TEXT("Label"), Actual, Expected); // int32/int64/SIZE_T/FName/FText/FString/FStringView…
TestEqual(TEXT("Approx"), ActualF, ExpectedF, 0.001f); // float/double/FVector/FRotator/FTransform take a tolerance
TestTrue(TEXT("Label"), bCondition); // also TestFalse, TestNotEqual
TestNotNull(TEXT("Label"), Ptr); // also TestNull, TestSamePtr, TestNotSamePtr
TestValid(TEXT("Label"), SharedOrWeakPtr); // also TestInvalid
AddError(FString::Printf(TEXT("Unexpected damage %d"), Damage)); // also AddWarning, AddInfo
AddErrorIfFalse(bOk, TEXT("Setup failed"));
UE_RETURN_ON_ERROR(Ptr != nullptr, TEXT("Ptr must not be null")); // adds error, returns false
// Expect (and swallow) a log line the code under test is supposed to emit.
AddExpectedMessage(TEXT("Inventory is full"), ELogVerbosity::Warning,
EAutomationExpectedMessageFlags::Contains);The pattern is a regex unless you use the …Plain variants (AddExpectedMessagePlain, AddExpectedErrorPlain). AddExpectedError(Pattern, MatchType, Occurrences, bIsRegex) is the shorthand that matches warnings and errors (it forwards ELogVerbosity::Warning, which is inclusive); the AddExpectedMessage overload without a verbosity matches every severity.
RunTest returns before latent commands run. Enqueue them, then let Update() return true when the step is finished. Enqueuing after return true; is unreachable code.
DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER(FMyWaitSecondsCommand, float, Duration);
bool FMyWaitSecondsCommand::Update()
{
return GetCurrentRunTime() >= Duration;
}
ADD_LATENT_AUTOMATION_COMMAND(FMyWaitSecondsCommand(2.0f)); // inside RunTest, before `return true;`DEFINE_LATENT_AUTOMATION_COMMAND through ..._FIVE_PARAMETER exist. To assert after the wait, derive from IAutomationLatentCommand and capture the FAutomationTestBase*.
BEGIN_DEFINE_SPEC(TClass, PrettyName, TFlags) / member declarations / END_DEFINE_SPEC(TClass) declares a BDD-style test whose body is void TClass::Define(). Inside Define() use Describe, It, LatentIt, BeforeEach, LatentBeforeEach, AfterEach (and xIt/xDescribe to disable a block). DEFINE_SPEC(TClass, PrettyName, TFlags) replaces the pair when the spec needs no members. Worked example in references/automation-test-patterns.md.
CQTest (module CQTest) is the fixture-based front end over the same framework. Assert is a FNoDiscardAsserter, so every assertion goes through ASSERT_THAT, which returns from the method on failure.
#include "CQTest.h"
TEST_CLASS(FMyInventoryTests, "MyGame.Inventory")
{
UMyInventoryComponent* Inventory = nullptr;
BEFORE_EACH() { Inventory = NewObject<UMyInventoryComponent>(GetTransientPackage()); }
TEST_METHOD(AddItem_WhenEmpty_StoresOne)
{
Inventory->AddItem(FName("Sword"), 1);
ASSERT_THAT(AreEqual(1, Inventory->GetItemCount(FName("Sword"))));
}
TEST_METHOD_WITH_TAGS(AddItem_WhenFull_Rejects, "[Slow][Inventory]")
{
Inventory->SetCapacity(0);
ASSERT_THAT(IsFalse(Inventory->AddItem(FName("Sword"), 1)));
}
};TEST_CLASS(ClassName, TestDir) uses FNoDiscardAsserter and DefaultFlags (EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::ProductFilter). Variants: TEST_CLASS_WITH_FLAGS(ClassName, TestDir, Flags), TEST_CLASS_WITH_TAGS, TEST_CLASS_WITH_BASE, TEST_CLASS_WITH_ASSERTS. Lifecycle macros are BEFORE_ALL()/AFTER_ALL() (static, once per fixture) and BEFORE_EACH()/AFTER_EACH() (override Setup()/TearDown()). Asserter helpers: IsTrue, IsFalse, IsNull, IsNotNull, AreEqual, AreNotEqual, AreEqualIgnoreCase, AreNotEqualIgnoreCase, IsNear(Expected, Actual, Epsilon) — each also takes a trailing failure message.
World, actor and async helpers (TestCommandBuilder, FSpawnHelper, FActorTestSpawner, FMapTestSpawner, TObjectBuilder, UTestGameInstance) are covered in references/automation-test-patterns.md.
AFunctionalTest (module FunctionalTesting) is an actor placed in a test map. PrepareTest, StartTest, IsReady_Implementation and OnTimeout are protected virtuals; FinishTest and the Assert* helpers are public.
// MyFunctionalTest.h
#pragma once
#include "CoreMinimal.h"
#include "FunctionalTest.h"
#include "MyFunctionalTest.generated.h"
UCLASS()
class MYGAME_API AMyFunctionalTest : public AFunctionalTest
{
GENERATED_BODY()
protected:
// PrepareTest() sets TimeLimit / PreparationTimeLimit; IsReady_Implementation()
// gates StartTest(); StartTest() asserts and calls FinishTest().
virtual void PrepareTest() override;
virtual bool IsReady_Implementation() override;
virtual void StartTest() override;
private:
UPROPERTY(EditInstanceOnly, Category = "MyGame")
TObjectPtr<AActor> TargetActor;
};Each override calls Super:: first. FinishTest(EFunctionalTestResult TestResult, const FString& Message) ends the run; EFunctionalTestResult is Default, Invalid, Error, Running, Failed, Succeeded, and Default lets the recorded assertions decide. Assertions are AssertTrue/AssertFalse (bool Condition, const FString& Message, const UObject* ContextObject = nullptr), AssertIsValid(UObject*, const FString&, const UObject* = nullptr), AssertEqual_Int/Float/Bool/Name/Object/Vector/Rotator/Transform/Quat and AssertValue_Int/Float/Double/DateTime (with an EComparisonMethod). Also TimeLimit, PreparationTimeLimit, SetTimeLimit(float, EFunctionalTestResult), LogMessage(const FString&) and StartStep/FinishStep. Full .cpp in references/automation-test-patterns.md.
Run every functional test in the current world with the Blueprint node UFunctionalTestingManager::RunAllFunctionalTests(WorldContextObject, bNewLog, bRunLooped, FailedTestsReproString) (the class is MinimalAPI and the function is not FUNCTIONALTESTING_API, so calling it from another module's C++ does not link), or from the command line:
UnrealEditor-Cmd.exe MyGame.uproject -ExecCmds="Automation RunTests MyGame.Functional" -unattended -nopause -testexit="Automation Test Queue Empty" -logAutomation also accepts List, RunTest, RunFilter <Filter>, RunAll, SetFilter, SetPriority, SetMinimumPriority, Quit and SoftQuit; chain them with ;.
Full command tables, the CSV and LLM workflows and the bottleneck-triage procedure are in references/profiling-commands.md.
# Capture at launch
UnrealEditor.exe MyGame.uproject -trace=cpu,frame,bookmark,counters,gpu,loadtime,log -tracehost=127.0.0.1
UnrealEditor.exe MyGame.uproject -trace=cpu,frame -tracefile=MyCapture.utrace
# Or from the console, mid-session
Trace.File D:/Captures/Run1.utrace cpu,frame,bookmark # or Trace.Send 127.0.0.1 cpu,frame
Trace.Enable counters
Trace.Bookmark WaveStarted
Trace.Stop # also Trace.Pause, Trace.Resume, Trace.StatusChannel names drop the Channel suffix and lowercase: cpu, gpu, frame, bookmark, counters, log, loadtime, task, memalloc, callstack, module, metadata, net, rhicommands, rendercommands, slate, assetmetadata, iostore, animation, region, screenshot.
#include "Stats/Stats.h" // DECLARE_*_STAT, SCOPE_CYCLE_COUNTER
#include "HAL/PlatformMisc.h" // SCOPED_NAMED_EVENT
#include "ProfilingDebugging/CpuProfilerTrace.h" // TRACE_CPUPROFILER_EVENT_SCOPE
#include "ProfilingDebugging/MiscTrace.h" // TRACE_BOOKMARK
#include "ProfilingDebugging/CountersTrace.h" // TRACE_*_COUNTER, TRACE_INT_VALUE
#include "ProfilingDebugging/CsvProfiler.h" // CSV_*
#include "ProfilingDebugging/ScopedTimers.h" // FScopedDurationTimer
DECLARE_STATS_GROUP(TEXT("MyGame"), STATGROUP_MyGame, STATCAT_Advanced);
DECLARE_CYCLE_STAT(TEXT("MyGame Tick"), STAT_MyGameTick, STATGROUP_MyGame);
CSV_DEFINE_CATEGORY(MyGame, true);
TRACE_DECLARE_INT_COUNTER(MyGameActiveEnemies, TEXT("MyGame/ActiveEnemies"));
void UMySubsystem::Tick(float DeltaTime)
{
SCOPE_CYCLE_COUNTER(STAT_MyGameTick); // stat system + Insights
TRACE_CPUPROFILER_EVENT_SCOPE(UMySubsystem::Tick); // Insights only, very cheap
CSV_SCOPED_TIMING_STAT(MyGame, SubsystemTick); // one CSV column
SCOPED_NAMED_EVENT(MyGame_Tick, FColor::Orange); // also visible to PIX/Razor
TRACE_COUNTER_SET(MyGameActiveEnemies, ActiveEnemyCount);
CSV_CUSTOM_STAT(MyGame, Enemies, ActiveEnemyCount, ECsvCustomStatOp::Set);
}
void UMySubsystem::BeginWave(int32 WaveNumber)
{
TRACE_BOOKMARK(TEXT("WaveStarted_%d"), WaveNumber); // vertical marker in Insights
CSV_EVENT(MyGame, TEXT("WaveStarted"));
double LoadSeconds = 0.0;
{
FScopedDurationTimer Timer(LoadSeconds); // accumulates into LoadSeconds
LoadWaveAssets(WaveNumber);
}
UE_LOGFMT(LogMyGame, Display, "Wave {Wave} loaded in {Seconds}s",
("Wave", WaveNumber), ("Seconds", LoadSeconds));
}QUICK_SCOPE_CYCLE_COUNTER(STAT_MyAdHocScope) declares a stat inline for a one-off measurement; TRACE_INT_VALUE(TEXT("MyGame/Spawned"), Count) and TRACE_FLOAT_VALUE emit a counter with no declaration; SCOPED_NAMED_EVENT_TEXT("Name", FColor::Yellow) takes a literal and SCOPED_NAMED_EVENT_F formats one.
stat unit first: it splits frame time into Game, Draw, RHIT and GPU. Then drill into the dominant thread with stat game, stat scenerendering, stat initviews, stat slate, stat threading, stat streaming, stat net, or stat MyGame for your own group. stat unitgraph plots the same numbers over time, stat fps shows frame rate, stat hitches flags spikes, stat namedevents emits stat names as profiler events for external tools.
stat memory / stat memoryplatform # engine categories / OS physical and virtual
memreport -full # dump to Saved/Profiling/MemReports
obj list class=Texture2D # loaded objects of a class, with sizesLaunch with -LLM and -trace=memalloc,callstack,module for Memory Insights; scope allocations with LLM_SCOPE(ELLMTag::EngineMisc) or a custom tag declared via LLM_DEFINE_TAG/LLM_DECLARE_TAG and entered with LLM_SCOPE_BYTAG. On Windows, non-editor builds default to MallocBinned3; override with -binnedmalloc2, -binnedmalloc, -ansimalloc or -stompmalloc.
snapshothitches -start arms an automatic trace snapshot whenever the stats system detects a hitch; snapshothitches -stop disarms it. It needs STATS and a non-Shipping build, and disables the Screenshot channel while armed so a stale screenshot cannot land in the snapshot tail.
Compiling with CSV_TRACK_UOBJECT_COUNT=1 (with CSV profiling enabled) records the live UObject count every frame as CSV stat Total in category ObjectCount, read from UObjectStats::GetUObjectCount(). Use it to catch object leaks over a long session without a full memory capture.
Everything in DrawDebugHelpers.h sits behind ENABLE_DRAW_DEBUG, which is UE_ENABLE_DEBUG_DRAWING = (!(UE_BUILD_SHIPPING || UE_BUILD_TEST) || WITH_EDITOR). In Test or Shipping game builds they become empty inline stubs (DrawDebugHelpers.h:180-185; defining SHIPPING_DRAW_DEBUG_ERROR=1 removes them so stray calls fail to compile), but arguments are still evaluated — wrap expensive call sites in #if ENABLE_DRAW_DEBUG.
#include "DrawDebugHelpers.h"
// LifeTime: -1 (default) or 0 draws one frame; > 0 is seconds.
// bPersistentLines = true keeps the shape until FlushPersistentDebugLines.
UWorld* World = GetWorld();
DrawDebugLine(World, Start, End, FColor::Red, false, 2.0f, 0, 2.0f);
DrawDebugPoint(World, Location, 8.0f, FColor::White, false, 2.0f, 0);
DrawDebugDirectionalArrow(World, Start, End, 40.0f, FColor::Cyan, false, 2.0f, 0, 2.0f);
DrawDebugBox(World, Center, Extent, FQuat::Identity, FColor::Blue, false, 2.0f, 0, 1.0f);
DrawDebugSphere(World, Center, 100.0f, 12, FColor::Green, false, 2.0f, 0, 1.0f);
DrawDebugCapsule(World, Center, 88.0f, 34.0f, FQuat::Identity, FColor::Yellow, false, 2.0f, 0, 1.0f);
DrawDebugString(World, Location, TEXT("Label"), nullptr, FColor::White, 2.0f, true, 1.0f);
FlushPersistentDebugLines(World); // and FlushDebugStrings(World)The Blueprint-facing UKismetSystemLibrary::DrawDebugLine/Arrow/Sphere/Capsule/String gate themselves, take FLinearColor and an EDrawDebugSceneDepthPriorityGroup, and are joined by PrintString(WorldContextObject, InString, bPrintToScreen, bPrintToLog, TextColor, Duration, Key).
ENABLE_VISUAL_LOG is PLATFORM_DESKTOP && !NO_LOGGING && UE_ENABLE_DEBUG_DRAWING. Open the timeline with Window > Visual Logger.
#include "VisualLogger/VisualLogger.h"
UE_VLOG(this, LogMyGame, Log, TEXT("State: %s"), *StateName);
UE_VLOG_UELOG(this, LogMyGame, Warning, TEXT("Lost target %s"), *TargetName); // also hits UE_LOG
UE_VLOG_LOCATION(this, LogMyGame, Verbose, GetActorLocation(), 20.0f, FColor::Green, TEXT("Here"));
UE_VLOG_SEGMENT(this, LogMyGame, Log, PathStart, PathEnd, FColor::Red, TEXT("Path"));
UE_VLOG_SPHERE(this, LogMyGame, Verbose, PatrolPoint, 50.0f, FColor::Blue, TEXT("Patrol"));
UE_VLOG_ARROW(this, LogMyGame, Log, GetActorLocation(), AimPoint, FColor::Yellow, TEXT("Aim")); // also _BOX, _CAPSULE
UE_CVLOG(bIsAlerted, this, LogMyGame, Log, TEXT("Alerted")); // also UE_CVLOG_SEGMENT, UE_CVLOG_LOCATION
FVisualLogger::Get().SetIsRecording(true); // and SetIsRecordingToFile / SetIsRecordingToTraceEvery macro early-outs on FVisualLogger::IsRecording(), so the arguments cost nothing when recording is off.
Press ' in PIE. Register a category from your module's StartupModule (add "GameplayDebugger" to PrivateDependencyModuleNames; wrap the registration and the category class in #if WITH_GAMEPLAY_DEBUGGER, which is 0 in Test/Shipping game builds by default — GameplayDebuggerCategory.h:10-11, TargetRules.cs:1125):
#include "GameplayDebugger.h" // in FMyGameModule::StartupModule()
if (IGameplayDebugger::IsAvailable())
{
IGameplayDebugger& Debugger = IGameplayDebugger::Get();
Debugger.RegisterCategory(TEXT("MyGame"),
IGameplayDebugger::FOnGetCategory::CreateStatic(&FMyDebuggerCategory::MakeInstance),
EGameplayDebuggerCategoryState::EnabledInGame);
Debugger.NotifyCategoriesChanged();
}FMyDebuggerCategory derives from FGameplayDebuggerCategory and overrides virtual void CollectData(APlayerController* OwnerPC, AActor* DebugActor) and virtual void DrawData(APlayerController* OwnerPC, FGameplayDebuggerCanvasContext& CanvasContext), feeding them with AddTextLine and AddShape. Call UnregisterCategory(TEXT("MyGame")) in ShutdownModule.
AHUD::ShowDebug(FName DebugType) toggles a named debug page (ShowDebug AI, ShowDebug Physics); ShowDebugToggleSubCategory(FName) toggles a sub-page and ShowDebugForReticleTargetToggle(TSubclassOf<AActor>) retargets it at whatever the reticle is over. Override virtual void ShowDebugInfo(float& YL, float& YPos) or bind AHUD::OnShowDebugInfo for your own page. The separate display, displayall and displayclear console commands print a named property of an object or class onto the HUD.
// In the AMyPlayerController class body. Exec works on PlayerController, Pawn, HUD,
// GameMode, GameState, CheatManager (or a UCheatManagerExtension) and GameInstance.
UFUNCTION(Exec)
void ToggleGodMode();// MyGameDebug.cpp — console objects register at static init
#include "HAL/IConsoleManager.h"
static FAutoConsoleCommand GMyDumpStatsCmd(
TEXT("MyGame.DumpStats"), TEXT("Dump gameplay stats"),
FConsoleCommandDelegate::CreateStatic(&FMyStatsDumper::Dump));
// World + args; prefer this for anything that touches gameplay in PIE.
static FAutoConsoleCommandWithWorldAndArgs GMySpawnItemCmd(
TEXT("MyGame.SpawnItem"), TEXT("Usage: MyGame.SpawnItem <Name>"),
FConsoleCommandWithWorldAndArgsDelegate::CreateStatic(&FMySpawner::SpawnFromConsole));
static TAutoConsoleVariable<float> CVarMyDamageScale(
TEXT("MyGame.DamageScale"), 1.0f, TEXT("Scales all outgoing damage."), ECVF_Cheat);
// FAutoConsoleVariableRef binds a console name to an existing int32/float/bool/FString/FName.
static float GMyDrawDistance = 5000.0f;
static FAutoConsoleVariableRef CVarMyDrawDistance(
TEXT("MyGame.DrawDistance"), GMyDrawDistance, TEXT("Gameplay draw distance."), ECVF_Default);Read a CVar with GetValueOnGameThread(), GetValueOnRenderThread() or GetValueOnAnyThread(). Common flags: ECVF_Default, ECVF_Cheat (disabled on shipping targets), ECVF_ReadOnly, ECVF_Scalability, ECVF_RenderThreadSafe. When a command's lifetime is tied to an object, register at runtime with IConsoleManager::Get().RegisterConsoleCommand(Name, Help, Delegate) and release the returned IConsoleCommand* with IConsoleManager::Get().UnregisterConsoleObject(Cmd).
| Do not emit | Use in 5.8 | Source |
|---|---|---|
UE_TRACE_BOOKMARK(...) | TRACE_BOOKMARK(Format, ...) | ProfilingDebugging/MiscTrace.h — no UE_TRACE_BOOKMARK exists |
Trace.Start [Channels] | Trace.File [Path] [Channels] | "'Trace.Start' is being deprecated in favor of 'Trace.File'" in TraceAuxiliary.cpp |
stat startfile / stat stopfile / stat startfileraw (.uestats) | Trace.File + UnrealInsights.exe | gated behind UE_ENABLE_STATS_FILE_DEPRECATED_IN_5_8 (default 0) in Stats/StatsFile.h |
stat gpu | ProfileGPU, DumpGPU, or the per-queue group stat GPU0_Graphics0 | GPU groups are built as STATGROUP_%s from GPU%d_%s%d in RHI/Private/GPUProfiler.cpp |
Unscoped flag names such as EditorContext | scope them: EAutomationTestFlags::EditorContext | EAutomationTestFlags is an enum class in Misc/AutomationTest.h |
EAutomationExpectedErrorFlags::… as a distinct type | EAutomationExpectedMessageFlags::… | the former is now a namespace alias of the latter |
UE_LOG_REF, UE_LOG_CLINKAGE | UE_LOG | marked "DO NOT USE … will be deprecated" in Logging/LogMacros.h |
-csvstatfile=Out.csv | -csvCaptureFrames=N plus CsvProfile StartFile=<name> | CsvProfiler.cpp parses csvCaptureFrames=, csvCategories=, csvMetadata=, csvGpuStats, csvExecCmds= and others, but no csvstatfile |
Assuming Test builds keep check/ensure: DO_CHECK and DO_ENSURE are USE_CHECKS_IN_SHIPPING / USE_ENSURES_IN_SHIPPING in both Test and Shipping, and both default to 0. Use verify() when the expression must always run, or set bUseChecksInShipping.
Logic inside a log or assert: UE_LOG(LogMyGame, Log, TEXT("%d"), AdvanceCounter()); stops advancing once NO_LOGGING is on, and check(Init()) stops initializing once DO_CHECK is 0. Compute into a local first, then log or assert on it.
Using Log and expecting console output: Display prints to the console; Log only reaches the log file. "My log line never appears" is almost always a Log-verbosity message.
Missing filter flag: every IMPLEMENT_*_AUTOMATION_TEST, DEFINE_SPEC and BEGIN_DEFINE_SPEC needs exactly one of SmokeFilter/EngineFilter/ProductFilter/PerfFilter/StressFilter/NegativeFilter plus at least one context flag, or the static_assert fails to compile.
Dropping a CQTest assertion result: the asserter methods are [[nodiscard]], so Assert.IsTrue(x); warns and keeps running after a failure. Always write ASSERT_THAT(IsTrue(x));.
DrawDebug* in a Shipping or Test game build: the calls become no-op stubs but their arguments (traces, string formatting) still run. Wrap the whole block in #if ENABLE_DRAW_DEBUG.
Skipping Super::StartTest(): AFunctionalTest::StartTest fires the Blueprint ReceiveStartTest event, so omitting Super:: silently disables every Blueprint-authored step in the same test actor.
ue-cpp-foundations — UObject basics, delegates, containers, the UFUNCTION/UPROPERTY specifier tablesue-module-build-system — Build.cs and Target.cs wiring, bBuildDeveloperTools, test module setup, plugin layoutue-editor-tools — editor utilities, commandlets and Slate tooling that host test and debug UIue-physics-collision — trace and sweep queries whose results you visualize with DrawDebug*ue-ai-navigation — behaviour trees, EQS and the AI-side Gameplay Debugger categoriesue-async-threading — task graph and async work that latent commands and the task trace channel observeue-gameplay-framework — GameMode, PlayerController, HUD and CheatManager, the hosts for Exec functionsue-materials-rendering — material instances, parameter collections, render targets and post process© quodsoler, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 2 other files (references) in skills/ue-testing-debugging of quodsoler/unreal-engine-skills.
Open the folder on GitHubat commit f3742d7
Ue Testing Debugging 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 |
|---|---|---|---|---|---|---|
| Ue Testing Debugging this skillquodsoler/unreal-engine-skills | 359 | — | ~8.1k | Automated safety check: Pass | MIT | |
| Debugging CodeJetBrains/skills | 363 | 1 repos | ~3.8k | Automated safety check: Pass | None | |
| Godot Debuggingjame581/GodotPrompter | 792 | — | ~3k | Automated safety check: Pass | MIT | |
| Unreal BridgeTornLux/UnrealBridge | 305 | — | ~8.4k | Automated safety check: Notes | MIT | |
| Unreal Blueprint Authoringflopperam/unreal-engine-mcp | 1.1k | — | ~1.6k | Automated safety check: Pass | None | |
| UMG Material MCPwinyunq/UnrealMotionGraphicsMCP | 207 | — | ~913 | Automated safety check: Pass | MIT |
JetBrains/skills
A skill your agent uses for debugger-driven runtime root-cause analysis in Rider-supported solutions and projects, including .NET/C, F, VB, C++, Unity, Unreal Engine, and other GameDev or…
jame581/GodotPrompter
A skill your agent uses when debugging Godot projects — remote debugger, print techniques, signal tracing, common error patterns and fixes
TornLux/UnrealBridge
Execute Python scripts inside a running Unreal Engine 5.3+ editor via TCP bridge.
flopperam/unreal-engine-mcp
Walks an agent through creating and editing Unreal Engine Blueprints with the Flopperam MCP's bp_* tools, from inspection to commit and verification.
winyunq/UnrealMotionGraphicsMCP
Creates, edits and compiles Unreal Engine 5.8 material assets as one HLSL Custom node through the UMG MCP bridge, instead of editing .uasset files directly.
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.
quodsoler/unreal-engine-skills
Unreal Engine C++ guidance for AActor and UActorComponent: lifecycle hooks, spawning, component creation and attachment, ticking, interfaces and composition.
quodsoler/unreal-engine-skills
Guides Unreal Engine C++ AI work across AI controllers, behavior trees, blackboards, perception, navmesh pathfinding, EQS and Smart Objects.
quodsoler/unreal-engine-skills
Reference for writing and debugging Unreal Engine 5.8 animation C++: AnimInstance and proxy, montages, notifies, curves, blend spaces, state machines, linked layers and root motion.
quodsoler/unreal-engine-skills
Picks and applies the right Unreal Engine C++ concurrency API, from UE::Tasks and FPipe to ParallelFor, FRunnable, locks and timers, with game-thread safety rules.
quodsoler/unreal-engine-skills
A skill your agent uses when playing, mixing or debugging sound in Unreal Engine — one-shot SFX, looping ambience, music, dialogue or procedural audio.
quodsoler/unreal-engine-skills
Reference for exposing Unreal Engine C++ to Blueprint and calling Blueprint from C++, covering UFUNCTION and UPROPERTY specifiers, latent and async nodes, and interfaces.
Works with
Categories
A skill your agent uses when writing or running Unreal Engine tests, adding logging, or profiling a build. Ue Testing Debugging is an agent skill from quodsoler/unreal-engine-skills. Use when writing or running Unreal Engine tests, adding logging, or profiling a build.
Ue Testing Debugging fits situations like: running Unreal Engine tests; profiling a build; the user mentions UELOG; DEFINELOGCATEGORY.
Run `npx skills add quodsoler/unreal-engine-skills --skill ue-testing-debugging -a claude-code`. Or copy the skill folder (skills/ue-testing-debugging in quodsoler/unreal-engine-skills) into .claude/skills/ue-testing-debugging in your project. Claude Code loads it when a task matches its description.
Run `npx skills add quodsoler/unreal-engine-skills --skill ue-testing-debugging -a codex`. Or copy the skill folder (skills/ue-testing-debugging in quodsoler/unreal-engine-skills) into .agents/skills/ue-testing-debugging 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 quodsoler/unreal-engine-skills --skill ue-testing-debugging -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ue-testing-debugging, .gemini/skills/ue-testing-debugging, .github/skills/ue-testing-debugging and .opencode/skills/ue-testing-debugging in your project.
SKILL.md names no scripts, command-line tools or credentials: Ue Testing Debugging is instructions for the agent only.
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.
Ue Testing Debugging is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 8.1k tokens (SKILL.md is roughly 33k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 9k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Ue Testing Debugging: Debugging Code (JetBrains/skills, 363 stars), Godot Debugging (jame581/GodotPrompter, 792 stars), Unreal Bridge (TornLux/UnrealBridge, 305 stars) and Unreal Blueprint Authoring (flopperam/unreal-engine-mcp, 1.1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
quodsoler (a GitHub user) maintains it in quodsoler/unreal-engine-skills, which has 359 GitHub stars. The repository holds 31 skills in this directory. The repository was last updated on September 28, 2026.
Source: quodsoler/unreal-engine-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.