Awesome-omni-skill unreal-engine-cpp-pro
Expert guide for Unreal Engine 5.x C++ development, covering UObject hygiene, performance patterns, and best practices.
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/unreal-engine-cpp-pro" ~/.claude/skills/diegosouzapw-awesome-omni-skill-unreal-engine-cpp-pro && rm -rf "$T"
manifest:
skills/development/unreal-engine-cpp-pro/SKILL.mdsource content
Unreal Engine C++ Pro
This skill provides expert-level guidelines for developing with Unreal Engine 5 using C++. It focuses on writing robust, performant, and standard-compliant code.
When to Use
Use this skill when:
- Developing C++ code for Unreal Engine 5.x projects
- Writing Actors, Components, or UObject-derived classes
- Optimizing performance-critical code in Unreal Engine
- Debugging memory leaks or garbage collection issues
- Implementing Blueprint-exposed functionality
- Following Epic Games' coding standards and conventions
- Working with Unreal's reflection system (UCLASS, USTRUCT, UFUNCTION)
- Managing asset loading and soft references
Do not use this skill when:
- Working with Blueprint-only projects (no C++ code)
- Developing for Unreal Engine versions prior to 5.x
- Working on non-Unreal game engines
- The task is unrelated to Unreal Engine development
Core Principles
-
UObject & Garbage Collection:
- Always use
forUPROPERTY()
member variables to ensure they are tracked by the Garbage Collector (GC).UObject* - Use
if you need to keep a root reference outside of a UObject graph, but preferTStrongObjectPtr<>
generally.addToRoot() - Understand the
check vsIsValid()
.nullptr
handles pending kill state safely.IsValid()
- Always use
-
Unreal Reflection System:
- Use
,UCLASS()
,USTRUCT()
,UENUM()
to expose types to the reflection system and Blueprints.UFUNCTION() - Minimize
when possible; preferBlueprintReadWrite
for state that shouldn't be trampled by logic in UI/Level BPs.BlueprintReadOnly
- Use
-
Performance First:
- Tick: Disable Ticking (
) by default. Only enable it if absolutely necessary. Prefer timers (bCanEverTick = false
) or event-driven logic.GetWorldTimerManager() - Casting: Avoid
in hot loops. Cache references inCast<T>()
.BeginPlay - Structs vs Classes: Use
structs for data-heavy, non-UObject types to reduce overhead.F
- Tick: Disable Ticking (
Naming Conventions (Strict)
Follow Epic Games' coding standard:
- Templates: Prefix with
(e.g.,T
,TArray
).TMap - UObject: Prefix with
(e.g.,U
).UCharacterMovementComponent - AActor: Prefix with
(e.g.,A
).AMyGameMode - SWidget: Prefix with
(Slate widgets).S - Structs: Prefix with
(e.g.,F
).FVector - Enums: Prefix with
(e.g.,E
).EWeaponState - Interfaces: Prefix with
(e.g.,I
).IInteractable - Booleans: Prefix with
(e.g.,b
).bIsDead
Common Patterns
1. Robust Component Lookup
Avoid
GetComponentByClass in Tick. Do it in PostInitializeComponents or BeginPlay.
void AMyCharacter::PostInitializeComponents() { Super::PostInitializeComponents(); HealthComp = FindComponentByClass<UHealthComponent>(); check(HealthComp); // Fail hard in dev if missing }
2. Interface Implementation
Use interfaces to decouple systems (e.g., Interaction system).
// Interface call check if (TargetActor->Implements<UInteractable>()) { IInteractable::Execute_OnInteract(TargetActor, this); }
3. Async Loading (Soft References)
Avoid hard references (
UPROPERTY(EditDefaultsOnly) TSubclassOf<AActor>) for massive assets which force load orders. Use TSoftClassPtr or TSoftObjectPtr.
UPROPERTY(EditAnywhere, BlueprintReadWrite) TSoftClassPtr<AWeapon> WeaponClassToLoad; void AMyCharacter::Equip() { if (WeaponClassToLoad.IsPending()) { WeaponClassToLoad.LoadSynchronous(); // Or use StreamableManager for async } }
Debugging
- Logging: Use
with custom categories.UE_LOGDEFINE_LOG_CATEGORY_STATIC(LogMyGame, Log, All); UE_LOG(LogMyGame, Warning, TEXT("Health is low: %f"), CurrentHealth); - Screen Messages:
if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Died!")); - Visual Logger: extremely useful for AI debugging. Implement
.IVisualLoggerDebugSnapshotInterface
Checklist before PR
- Does this Actor need to Tick? Can it be a Timer?
- Are all
members wrapped inUObject*
?UPROPERTY - Are hard references (TSubclassOf) causing load chains? Can they be Soft Ptrs?
- Did you clean up verified delegates in
?EndPlay