unreal-guidelines
Skill1 starsChanged 4 months agoMITView on GitHub
Use when writing, reviewing, or designing Unreal Engine 5 C++ and project tooling where modules, reflection and GC, threading, Chaos physics, rendering, Niagara, editor automation, builds, or Rust/C FFI matter.
In this repository30 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- blind-reviewSkill
- c-guidelinesSkill
- cpp-guidelinesSkill
- dast-staging-guidelinesSkill
- data-engineering-guidelinesSkill
- diagramming-guidelinesSkill
- java-guidelinesSkill
- jj-guidelinesSkill
- kotlin-guidelinesSkill
- lua-guidelinesSkill
- python-guidelinesSkill
- re-provenance-guidelinesSkill
- reverse-engineering-guidelinesSkill
- rust-guidelinesSkill
- sast-triage-guidelinesSkill
- scala-guidelinesSkill
- security-review-guidelinesSkill
- spark-guidelinesSkill
- spark-pyspark-guidelinesSkill
- spark-scala-guidelinesSkill
- sql-guidelinesSkill
- supply-chain-guidelinesSkill
- swift-guidelinesSkill
- technical-writing-guidelinesSkill
- terraform-guidelinesSkill
- tool-prioritySkill
- tutoring-guidelinesSkill
- typescript-guidelinesSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
13 rules. About 0 are common, 7 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 17
Treat any feature, status, or deprecation absent from the release notes or the engine source as unverified, and say so.
- Very specific: line 22
Keep PCHUsage = UseExplicitOrSharedPCHs and include what you use (IWYU).
- Very specific: line 25
Never hold a raw UObject* in a TArray, TMap, or struct without UPROPERTY.
- Very specific: line 26
Create objects with NewObject, CreateDefaultSubobject, or SpawnActor.
- Distinctive: line 55
Do not default to Visual Studio or Windows-only tools.
- Distinctive: line 63
No exceptions or panics cross the boundary.
- Distinctive: line 65
Keep the foreign API thread contract explicit and guard it with one lock when it is not thread safe.
- Very specific: line 90
Look for Nanite and Lumen cost in stat gpu, draw calls in stat rhi, tick cost in stat game, and GC spikes in the Insights timing view.
- Very specific: line 91
Do not tune from stat fps alone.
- Very specific: line 95
Use exact repo-native gates first (just build, just check-all, or similar recipes when present).
- Distinctive: line 103
Do not install tooling speculatively.
- Distinctive: line 121
When reviewing, lead with severity-ranked findings with file and line evidence.
- Distinctive: line 123
When implementing, make the smallest coherent change, add or update tests for observable behavior, and record the exact build and test …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Unreal Guidelines
Use this as the shared Unreal Engine rubric for agents. It targets UE 5.8 on macOS and Linux. Prefer repo-local conventions when they are deliberate and documented, but push back when they cause GC bugs, thread races, or unreproducible assets. Pair it with cpp-guidelines for language-level rules.
Source Of Truth
- Epic C++ Coding Standard and UE 5.8 documentation: https://dev.epicgames.com/documentation/en-us/unreal-engine/
- UE 5.8 release notes: https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-5-8-release-notes
- Engine source under
Engine/Sourceis the truth for API signatures andUE_DEPRECATEDmarkers. - The repo's
Build.cs,Target.cs,.uproject,.uplugin,Config/*.ini, and justfile decide local conventions and gates.
Treat any feature, status, or deprecation absent from the release notes or the engine source as unverified, and say so.
Core Rubric
- Modules: keep
PublicDependencyModuleNamesto modules whose types appear in public headers. Put everything else inPrivateDependencyModuleNames. Do not widenPublicIncludePathsto silence an include error. - Keep
PCHUsage = UseExplicitOrSharedPCHsand include what you use (IWYU). Do not includeCoreMinimal.hplus broad engine headers in headers that a forward declaration satisfies. - Plugins: declare module
Type,LoadingPhase, and plugin dependencies in the.uplugin. Enable plugins in the.uprojectonly when used. - Reflection: every
UObjectpointer member needsUPROPERTY()so the GC sees it. UseTObjectPtr<T>for member properties,TWeakObjectPtr<T>for non-owning references, andTStrongObjectPtr<T>for owners that are notUObjects. UseAddToRootonly as a last resort with a matchingRemoveFromRoot. - Never hold a raw
UObject*in aTArray,TMap, or struct withoutUPROPERTY. Check withIsValid(Obj), notObj != nullptr, for objects that can be destroyed. - Create objects with
NewObject,CreateDefaultSubobject, orSpawnActor. Never use rawnewon aUObject. - Types:
FStringfor text work,FNamefor identifiers,FTextfor user-visible text,TArray/TMap/TSetfor containers,TSharedPtr/TUniquePtrfor non-UObjects.FVector,FRotator, andFTransformare double precision in UE5. Usefloatonly where an API requires it. - Style: Epic prefixes A (actor), U (object), F (struct), E (enum), I (interface), T (template). Booleans start with
b. Wrap literals inTEXT(). Declare aDEFINE_LOG_CATEGORYper module and useUE_LOGwith a verbosity. - Assertions:
checkhalts and is for programmer invariants.ensurereports once and continues.verifykeeps its expression in shipping builds. Never put required side effects insidecheck. - Lifetime: do not call
GetWorld()or touch other objects in a constructor. UsePostInitializeComponents,BeginPlay, andEndPlayfor runtime setup and teardown. Register created components. SetPrimaryActorTick.bCanEverTickonly when the actor needsTick, and pick the lowest-cost tick group. - Threading: mutate
UObjects on the game thread only. UseAsyncTask(ENamedThreads::GameThread, ...)to return results. PreferUE::Tasks,AsyncTask, orParallelForover rawFRunnable. Guard shared data withFCriticalSectionplusFScopeLock, and keep the critical section short. - Render thread: enqueue with
ENQUEUE_RENDER_COMMAND, capture by value, and never capture a rawUObject*that the GC can free. Record work onFRHICommandListonly on the render thread. - Physics: Chaos uses centimetres. Convert forces from newtons by 100 and torques from N m by 10,000 (kg cm²/s²), never by 100. Use
AddForceAtLocationfor off-centre forces. WithbTickPhysicsAsync, put physics input inAsyncPhysicsTickActor(AsyncPhysicsTick) at the fixed step, not inTick. Check substepping settings and physical materials before tuning forces. - Rendering: Nanite supports tessellation and displacement via materials, but cost depends on the material. Use
UMaterialInstanceDynamicfor per-instance parameters and create it once. Upload texture data withUpdateTextureRegionsor a render command, and keep the source buffer alive until the command completes. Set Niagara user parameters with typed setters (SetVariableFloat,SetVariableVec3) on a cached component. - Input: use Enhanced Input (
UInputAction,UInputMappingContext). Do not add new legacy axis or action mappings. - Framework: put rules in
AGameModeBase, replicated match state inAGameStateBase, input inAPlayerController, and possession inAPawn. UseUGameInstanceSubsystem,UWorldSubsystem, orULocalPlayerSubsystemfor services with a clear lifetime. - Replication: mark state
UPROPERTY(Replicated)orReplicatedUsing, implementGetLifetimeReplicatedProps, checkHasAuthority()before mutating, and give each RPCServer,Client, orNetMulticastwithReliableonly when loss is unacceptable. ValidateServerRPC input. - Assets: never hand-edit
.uassetor.umap. Generate them with editor Python or Geometry Script, and commit the generator. Layer config asBasethenDefault*.inithen platform thenSaved. Change project settings inDefault*.ini. - Version hygiene: check
UE_DEPRECATEDbefore using an API. Cite the 5.8 release notes for status. Label Experimental and Beta features as such in code review output.
UE 5.8 Status Facts (from the release notes)
- Production Ready: Megalights, Movie Render Graph.
- Beta: Lumen Lite, Control Rig Physics.
- Experimental: MCP Server plugin, Fog Screen Space Scattering, Substrate NPR (Toon) Shading, Mesh Terrain, Fast Geometry Streaming, Procedural Vegetation Editor (Nanite foliage).
- Deprecated or renamed:
QueueSubtitle(useQueueSingleSubtitle),AllowRemoteNetworkService(nowRemoteNetworkService),FastGeoStreaming.ini(nowDefaultFastGeoStreaming.ini). Removed:EProxyCreationState::Pending,UFastGeoComponentEditorProxy.
Build And Editor Tooling
- Build with
Engine/Build/BatchFiles/Mac/Build.sh <Target>Editor Mac Development -Project=<x.uproject> -WaitMutex. On Linux use the matchingLinuxscript. Add-NoUBAwhen the Unreal Build Accelerator is unstable on that machine. - Hot reload: an open editor makes UBT write a hot-reload module name that a
-gamerun ignores. DeleteBinaries/before a headless run after such a build. - Live Coding changes function bodies only. Header, reflection, and
Build.cschanges need a full build. RunUBT.sh -mode=GenerateClangDatabasewritescompile_commands.jsonfor clangd and CLion.- Set
MACOSX_DEPLOYMENT_TARGETto matchEngine/Config/Mac/Mac_SDK.jsonwhen linking a static library. - Do not default to Visual Studio or Windows-only tools.
- Editor scripts:
UnrealEditor-Cmd <project> -run=pythonscript -script=<file>. Commandlets run with-run=<Name>. Automation tests useIMPLEMENT_SIMPLE_AUTOMATION_TESTorIMPLEMENT_COMPLEX_AUTOMATION_TEST. - MCP Server plugin (Experimental): the editor serves MCP over HTTP with the meta-tools
list_toolsets,describe_toolset, andcall_tool. Calldescribe_toolsetbeforecall_tool. Data sent through it is Licensed Technology under the UE EULA. - Headless checks:
UnrealEditor <project> -game -Windowed ...exits 0 even afterRequestExitWithStatus(false, 1). Read the verdict from the log, not the exit code.
FFI With Rust Or C
- Link one static library through
PublicAdditionalLibrariesand expose hand-written C headers throughPublicIncludePaths. Wrap headers inextern "C". - No exceptions or panics cross the boundary. Return status codes and keep the error text retrievable.
- One
UObjectowns each foreign handle. Create it inInitializeand free it inDeinitializeorBeginDestroy. Never copy the handle. - Keep the foreign API thread contract explicit and guard it with one lock when it is not thread safe.
Anti-Slop Checklist
Reject or fix these patterns on sight, whether writing or reviewing:
- Raw
newfor aUObject, ordeleteon one. - A
UObject*member or container element withoutUPROPERTY, which the GC will free. GetWorld(),GetOwner(), or other object lookups in a constructor.Tickdoing work that a timer, delegate, or event can do.FindObject,LoadObject, orTActorIteratorby string or class in a hot path.StaticLoadObjector synchronous loads on the game thread during play instead of soft references and async load.- Blueprint-only logic that C++ tests cannot reach, when the logic is core gameplay.
UE_LOGwithout a category, orUE_LOGevery frame atLogverbosity.- Hard-coded asset paths in C++ without a
TSoftObjectPtror a config property. - Float literals and
floatfor world positions, which loses double precision. - Hand-edited generated assets, or a generator that is not committed.
- Physics forces applied in
TickwithDeltaTimescaling when the async physics step owns them. - Creating
UMaterialInstanceDynamicor Niagara components every frame. - Comments that restate the declaration, and
UFUNCTIONorUPROPERTYspecifiers with no reason.
Performance
- Measure before changing. Use Unreal Insights (CPU, GPU, memory, loading traces),
stat unit,stat gpu,stat game, andProfileGPU. - Report which of game thread, render thread, GPU, or RHI thread is the limit before proposing a fix.
- Look for Nanite and Lumen cost in
stat gpu, draw calls instat rhi, tick cost instat game, and GC spikes in the Insights timing view. - Do not tune from
stat fpsalone. Capture a trace on the target build configuration, not the editor.
Verification
Use exact repo-native gates first (just build, just check-all, or similar recipes when present). Then use these when the repo has them:
- A UBT build of the editor target with the repo's exact flags.
clang-formatoverSource/**/*.hand*.cpp, plus any lint gate (for example CRLF in tracked files).- Automation tests run through
UnrealEditor-Cmd ... -ExecCmds="Automation RunTests <Filter>; Quit". - Headless
-gamechecks that read an explicit PASS or FAIL line from the log. - Unreal Insights captures for performance claims.
Do not install tooling speculatively. State which checks were not run.
Adversarial Checklist
Push back when a change or suggestion hits these traps:
AddToRootto stop a GC crash hides a missingUPROPERTY. PreferUPROPERTY,TStrongObjectPtr, or a subsystem owner.- Touching a
UObjectfromAsyncTaskor the physics thread races the GC and the game thread. Copy plain data under a lock and apply it on the game thread. - Forces in newtons on Chaos are 100 times too weak. Scale to centimetre units and name the unit in the identifier.
- Capturing
thisor a raw pointer in a render command or lambda outlives the object. Capture values or aTWeakObjectPtr, and re-check validity. - Trusting
-gameexit code 0 reports success after a failure. Read the log verdict. - Editing generated
.uassetfiles cannot be reviewed or reproduced. Change the generator. - Panics or C++ exceptions across the FFI boundary abort the editor. Catch at the boundary and return a status.
- Depending on an Experimental feature (MCP Server, Mesh Terrain) without a fallback or a stated risk. Mark the status and isolate the dependency.
- Large
UpdateTextureRegionsevery frame with a freed or reused source buffer corrupts the upload. Keep the buffer alive until the cleanup callback and measure the upload size.
Output Contract
When reviewing, lead with severity-ranked findings with file and line evidence. Each finding states the risk (crash, race, GC, cost, or reproducibility) and the safer Unreal direction. Mark the status of any Experimental or Beta feature you rely on. Separate verified facts from inferences.
When implementing, make the smallest coherent change, add or update tests for observable behavior, and record the exact build and test commands with their results. State which checks were not run.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

