How: Developed by Epic Games, first released in 1998 with the game Unreal. UE4 (2014) brought it to modern PBR/physically-based era. UE5 (2022) introduced Nanite and Lumen.
Who: Founded by Tim Sweeney. Epic Games continues active development.
Why: To push real-time graphics to cinematic quality — used in AAA games, films, archviz, automotive, and XR.
Introduction
Unreal Engine 5 is the industry-leading real-time 3D engine. It uses C++ for core gameplay and Blueprints (visual scripting) for rapid prototyping. UE5 features Nanite (virtualized geometry), Lumen (dynamic GI), and a full suite of tools for games, film, and simulation.
Advantages
Nanite — render billions of polygons with no LOD setup.
Lumen — fully dynamic global illumination and reflections.
Blueprint visual scripting — no C++ needed to prototype.
World Partition — seamless open-world streaming.
MetaHuman — photorealistic human characters.
Free to use — 5% royalty only after $1M revenue.
Source code available on GitHub.
Disadvantages
Very heavy — editor uses 8–16GB RAM, needs a powerful GPU.
Steep learning curve — massive feature set.
Compile times for C++ can be long.
Overkill for simple 2D or small indie games.
Editor & Project Setup
Editor Layout
Viewport — 3D scene view (perspective/orthographic)
Content Browser — All project assets (bottom panel)
Outliner — Scene hierarchy (top right)
Details Panel — Properties of selected actor (right)
Toolbar — Play, Build, Source Control buttons (top)
Modes Panel — Select, Landscape, Foliage, Mesh Paint modes
Viewport Navigation
RMB + WASD — Fly through scene
RMB + QE — Move up/down
Alt + LMB — Orbit around selection
Alt + RMB — Zoom
F — Focus on selected actor
G — Toggle game view (hide editor gizmos)
Ctrl + Space — Open Content Browser
Project Structure
/Content/ All game assets (textures, meshes, blueprints, maps)
/Source/ C++ source files
/Config/ Project settings (.ini files)
/Plugins/ Engine and project plugins
/Saved/ Logs, screenshots, autosaves
/Intermediate/ Compiled binaries (auto-generated)
Key files:
MyProject.uproject — Project descriptor
MyProject.sln — Visual Studio solution
Key Shortcuts
Ctrl+S Save current level
Ctrl+Z / Y Undo / Redo
W / E / R Translate / Rotate / Scale gizmo
Alt+drag Duplicate actor
End Snap actor to floor
P Toggle Play-in-Editor (PIE)
Ctrl+P Quick asset search (Content Browser)
Shift+F1 Release mouse during PIE
Core Concepts — Actors & Components
Actor
Actor — the base class for everything placed in a level.
Every object in the world (character, light, camera, trigger) is an Actor.
Lifecycle:
Constructor → object created (CDO — Class Default Object)
BeginPlay() → actor enters the game world
Tick(DeltaTime) → called every frame
EndPlay() → actor removed from world
Destroyed() → actor fully destroyed
Components
Components add functionality to Actors.
Common Components:
UStaticMeshComponent — renders a static 3D mesh
USkeletalMeshComponent — renders an animated mesh with skeleton
UCapsuleComponent — collision capsule (used for characters)
UBoxComponent — box collision
USphereComponent — sphere collision
UCharacterMovementComponent — handles character physics/movement
UCameraComponent — camera view
USpringArmComponent — camera boom (follows character)
UAudioComponent — plays audio
UPointLightComponent — point light
UParticleSystemComponent — particle effects (Cascade)
UNiagaraComponent — particle effects (Niagara, modern)
UWidgetComponent — 3D UI widget in world space
Blueprints are Unreal's node-based visual scripting system.
Every Blueprint is a class — it can extend any C++ class.
Types:
Blueprint Class — extends Actor, Character, etc. (most common)
Level Blueprint — per-level scripting (triggers, cinematics)
Blueprint Interface — define functions any Blueprint can implement
Blueprint Macro Library — reusable macro nodes
Blueprint Function Library — reusable static functions
Animation Blueprint — controls skeletal animation state machine
Blueprint Basics
Event Graph:
Event BeginPlay → executes once when game starts
Event Tick → executes every frame (has DeltaSeconds pin)
Event Hit → called on collision
Event Overlap → called on overlap begin/end
Nodes:
Function call — white exec pin (sequence)
Pure function — no exec pin (math, getters)
Variable get/set — blue (object ref), green (bool), red (float), etc.
Branch — if/else
Sequence — run multiple outputs in order
ForEach Loop — iterate array
Cast To — safe downcast (Cast To AMyCharacter)
Delay — wait N seconds then continue
Blueprint Communication
Direct Reference:
Get reference to actor → call function on it
Cast To:
Cast To APlayerCharacter → access player-specific functions
Event Dispatcher (like signals):
Define dispatcher → bind in other BP → call to broadcast
Blueprint Interface:
Define interface function → implement in any BP
Call without knowing exact type (polymorphism)
Game Instance:
Persistent data across levels (score, settings)
Blueprint vs C++
Blueprints:
+ Fast to prototype
+ Visual, designer-friendly
+ No compile step
- Slower execution than C++
- Hard to diff/merge in version control
- Gets messy at scale ("spaghetti blueprints")
C++:
+ Full performance
+ Better for complex logic, algorithms
+ Version control friendly
- Requires compile
- Steeper learning curve
Best practice: Core systems in C++, expose to Blueprint for designers.
C++ in Unreal Engine
UObject & Macros
// All Unreal classes use UCLASS, UPROPERTY, UFUNCTION macros// These enable reflection, serialization, Blueprint exposure, GCUCLASS()class MYGAME_API AMyActor : public AActor{ GENERATED_BODY()public: AMyActor(); // Exposed to Blueprint and editor UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats") float Health = 100.f; UPROPERTY(VisibleAnywhere, BlueprintReadOnly) UStaticMeshComponent* Mesh; // Callable from Blueprint UFUNCTION(BlueprintCallable, Category = "Combat") void TakeDamage(float Amount); // Implementable in Blueprint UFUNCTION(BlueprintImplementableEvent) void OnDeath(); // C++ default, overridable in Blueprint UFUNCTION(BlueprintNativeEvent) void OnHit(); virtual void OnHit_Implementation();protected: virtual void BeginPlay() override; virtual void Tick(float DeltaTime) override;};
UPROPERTY Specifiers
UPROPERTY(EditAnywhere) // editable in editor (instance + CDO)UPROPERTY(EditDefaultsOnly) // editable only in Blueprint defaultsUPROPERTY(EditInstanceOnly) // editable only on placed instancesUPROPERTY(VisibleAnywhere) // visible but not editableUPROPERTY(BlueprintReadWrite) // read + write from BlueprintUPROPERTY(BlueprintReadOnly) // read only from BlueprintUPROPERTY(Replicated) // synced over networkUPROPERTY(ReplicatedUsing=OnRep_Health) // replicated with callbackUPROPERTY(Transient) // not saved to diskUPROPERTY(SaveGame) // included in save game serializationUPROPERTY(Category = "Combat") // organizes in Details panelUPROPERTY(meta = (ClampMin = "0", ClampMax = "100"))
UFUNCTION Specifiers
UFUNCTION(BlueprintCallable) // callable from BlueprintUFUNCTION(BlueprintPure) // no exec pin, no side effectsUFUNCTION(BlueprintImplementableEvent) // implemented in BlueprintUFUNCTION(BlueprintNativeEvent) // C++ default + Blueprint overrideUFUNCTION(Server, Reliable) // runs on server (RPC)UFUNCTION(Client, Reliable) // runs on owning client (RPC)UFUNCTION(NetMulticast, Unreliable) // runs on all clientsUFUNCTION(Exec) // console commandUFUNCTION(CallInEditor) // button in editor Details panel
APawn — Any actor that can be possessed/controlled
ACharacter — Pawn with mesh, capsule, movement component
APlayerController — Translates player input → Pawn actions
AAIController — Controls AI Pawns
AGameModeBase — Rules of the game (win/lose, spawn, teams)
AGameStateBase — Replicated game state (score, timer)
APlayerState — Per-player replicated state (name, score)
UGameInstance — Persistent across levels (settings, session)
AHUD — Heads-up display (legacy, prefer UMG)
APlayerCameraManager — Controls camera behavior
// Declare delegate typeDECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChanged, float, NewHealth);// In class:UPROPERTY(BlueprintAssignable)FOnHealthChanged OnHealthChanged;// Broadcast (fire event)OnHealthChanged.Broadcast(Health);// Bind in C++OnHealthChanged.AddDynamic(this, &AMyHUD::UpdateHealthBar);// Bind in Blueprint: assign to OnHealthChanged event// Single-cast delegate (not multicast)DECLARE_DELEGATE_OneParam(FOnDeath, AActor*);FOnDeath OnDeath;OnDeath.BindUObject(this, &AMyActor::HandleDeath);OnDeath.ExecuteIfBound(this);
Casting & Type Checking
// Cast (returns nullptr if wrong type)AMyCharacter* Player = Cast<AMyCharacter>(OtherActor);if (Player){ Player->TakeDamage(25.f);}// IsA — type check without castif (OtherActor->IsA<AEnemy>()){ // it's an enemy}// GetClassUE_LOG(LogTemp, Log, TEXT("Class: %s"), *OtherActor->GetClass()->GetName());
// In constructor — enable overlapTriggerBox->SetGenerateOverlapEvents(true);// Bind in BeginPlayTriggerBox->OnComponentBeginOverlap.AddDynamic(this, &AMyTrigger::OnOverlapBegin);TriggerBox->OnComponentEndOverlap.AddDynamic(this, &AMyTrigger::OnOverlapEnd);void AMyTrigger::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult){ if (AMyCharacter* Player = Cast<AMyCharacter>(OtherActor)) { Player->EnterZone(this); }}
Physics Bodies
// Enable physics simulation on meshMesh->SetSimulatePhysics(true);Mesh->SetEnableGravity(true);// Apply impulseMesh->AddImpulse(FVector(0, 0, 1000.f), NAME_None, true); // true = velocity change// Apply forceMesh->AddForce(FVector(500.f, 0, 0));// Set linear velocityMesh->SetPhysicsLinearVelocity(FVector(0, 0, 500.f));// Set massMesh->SetMassOverrideInKg(NAME_None, 50.f);
Animation System
Animation Blueprint
Animation Blueprint (ABP) controls skeletal mesh animation.
Two graphs:
Event Graph — logic (update variables: speed, is_jumping, etc.)
Anim Graph — state machine / blend tree (outputs final pose)
State Machine:
States: Idle, Walk, Run, Jump, Fall, Land
Transitions: conditions between states (Speed > 10 → Walk)
Blend Spaces:
1D BlendSpace — blend animations by one axis (speed: idle→walk→run)
2D BlendSpace — blend by two axes (speed + direction → strafe)
Anim Notifies
Anim Notify — event fired at a specific frame in an animation
Uses:
- Play footstep sound at foot-down frame
- Spawn projectile at attack frame
- Enable/disable collision during attack
In C++:
// Override in AnimInstance or listen via delegateUFUNCTION()void OnFootstep(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, FName NotifyName);
Inverse Kinematics (IK)
IK solves joint positions to reach a target.
Common uses:
Foot IK — feet conform to uneven terrain
Hand IK — hands grip weapons/objects correctly
Look At IK — head/eyes track a target
UE5 IK Rig + IK Retargeter:
- IK Rig: define IK chains and goals
- IK Retargeter: retarget animations between different skeletons
Control Rig:
- Procedural animation system
- Full-body IK, custom rigs, runtime deformation
UMG is Unreal's UI system — drag-and-drop widget designer.
Common Widgets:
Text Block — display text
Button — clickable button
Image — display texture/material
Progress Bar — health/loading bar
Slider — value slider
Check Box — toggle
Editable Text — text input
Canvas Panel — free-position layout
Vertical/Horizontal Box — stacked layout
Grid Panel — grid layout
Scroll Box — scrollable container
Overlay — stack widgets on top of each other
// In Widget Blueprint C++ classUCLASS()class UMyHUDWidget : public UUserWidget{ GENERATED_BODY()public: // Bind to widget in designer (must match widget name) UPROPERTY(meta = (BindWidget)) UProgressBar* HealthBar; UPROPERTY(meta = (BindWidget)) UTextBlock* ScoreText; // Optional bind (won't error if missing) UPROPERTY(meta = (BindWidgetOptional)) UButton* PauseButton; void UpdateHealth(float Percent) { HealthBar->SetPercent(Percent); } void UpdateScore(int32 Score) { ScoreText->SetText(FText::AsNumber(Score)); }};
Audio System
Sound Assets
Sound Wave — raw audio file (.wav, .ogg)
Sound Cue — node-based audio graph (randomize, loop, mix)
Sound Attenuation — defines 3D falloff, spatialization settings
Sound Class — volume group (Master, Music, SFX, Voice)
Sound Mix — adjust class volumes (e.g., duck music during dialogue)
MetaSound — UE5 procedural audio system (replaces Sound Cue)
Playing Audio
#include "Kismet/GameplayStatics.h"// Play at location (fire and forget)UGameplayStatics::PlaySoundAtLocation(this, JumpSound, GetActorLocation());// Play 2D (non-spatial, UI/music)UGameplayStatics::PlaySound2D(this, MenuMusic);// Spawn persistent audio componentUAudioComponent* AudioComp = UGameplayStatics::SpawnSoundAtLocation( this, FootstepSound, GetActorLocation());AudioComp->SetVolumeMultiplier(0.8f);AudioComp->SetPitchMultiplier(FMath::RandRange(0.9f, 1.1f));// StopAudioComp->Stop();// Attached audio component (follows actor)UAudioComponent* Comp = UGameplayStatics::SpawnSoundAttached( EngineSound, RootComponent);
AI System
Behavior Tree + Blackboard
Blackboard — shared data store for AI (key-value pairs)
Keys: TargetActor, PatrolPoint, IsAlerted, Health
Behavior Tree — hierarchical task graph
Selector — try children until one succeeds
Sequence — run children in order until one fails
Task — leaf node (Move To, Wait, Play Animation, custom)
Decorator — condition gate (Is Target Visible?, Has Ammo?)
Service — runs in background (update target location every 0.5s)
// Move to actorMoveToActor(TargetActor, 150.f); // 150 = acceptance radius// Move to locationMoveToLocation(TargetLocation);// Check if path existsUNavigationSystemV1* NavSys = UNavigationSystemV1::GetCurrent(GetWorld());FNavLocation Result;bool bFound = NavSys->GetRandomReachablePointInRadius( GetActorLocation(), 1000.f, Result);// NavMesh setup: place NavMeshBoundsVolume in level, press P to visualize
Multiplayer & Networking
Replication Basics
Unreal uses a Client-Server model.
Server is authoritative — owns game state.
Clients predict locally, server corrects.
Enable replication on Actor:
bReplicates = true; // replicate actor existence
SetReplicateMovement(true); // replicate transform
Replicate a variable:
UPROPERTY(Replicated)
float Health;
// Must implement GetLifetimeReplicatedProps:
void AMyActor::GetLifetimeReplicatedProps(
TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyActor, Health);
DOREPLIFETIME_CONDITION(AMyActor, Ammo, COND_OwnerOnly);
}
RepNotify
// Called on clients when variable changesUPROPERTY(ReplicatedUsing = OnRep_Health)float Health;UFUNCTION()void OnRep_Health(){ // Update health bar UI UpdateHealthBar(Health);}
RPCs (Remote Procedure Calls)
// Server RPC — client calls, runs on serverUFUNCTION(Server, Reliable, WithValidation)void ServerFire(FVector Direction);void AMyCharacter::ServerFire_Implementation(FVector Direction){ // Authoritative fire logic SpawnProjectile(Direction);}bool AMyCharacter::ServerFire_Validate(FVector Direction){ return Direction.IsNormalized(); // anti-cheat validation}// Multicast RPC — server calls, runs on all clientsUFUNCTION(NetMulticast, Unreliable)void MulticastPlayEffect(FVector Location);void AMyCharacter::MulticastPlayEffect_Implementation(FVector Location){ UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), HitEffect, Location);}// Client RPC — server calls, runs on owning client onlyUFUNCTION(Client, Reliable)void ClientShowMessage(const FString& Message);
Network Roles
// Check where code is runningHasAuthority() // true on serverIsLocallyControlled() // true on owning clientGetLocalRole() == ROLE_Authority // serverGetLocalRole() == ROLE_AutonomousProxy // owning clientGetLocalRole() == ROLE_SimulatedProxy // other clients// Common patternif (HasAuthority()){ // Server-only logic (damage, scoring, spawning)}
Rendering — UE5 Features
Nanite (Virtualized Geometry)
Nanite renders micro-polygon geometry — billions of triangles with no LOD setup.
How it works:
- Meshes stored as hierarchical clusters
- GPU selects which clusters to render based on screen size
- Only pixels that matter are shaded
- Effectively unlimited polygon count
Enable: Static Mesh → Details → Nanite → Enable Nanite Support
Limitations:
- No deforming meshes (skeletal, cloth, particles)
- No translucency
- Requires DX12 / Vulkan
Lumen (Dynamic Global Illumination)
Lumen provides fully dynamic GI and reflections — no baking required.
How it works:
- Traces rays against Signed Distance Fields (SDF) of meshes
- Screen traces for near-field detail
- Hardware ray tracing optional for higher quality
Enable: Project Settings → Rendering → Global Illumination → Lumen
Quality modes:
Software Lumen — runs on any DX11+ GPU
Hardware Lumen — requires RTX/RDNA2, higher quality reflections
Virtual Shadow Maps (VSM)
VSM replaces traditional shadow maps in UE5.
Features:
- Very high resolution (16k virtual resolution)
- Only renders shadow pages that are visible
- Works with Nanite geometry
- Supports many dynamic lights efficiently
Enable: Project Settings → Rendering → Shadows → Virtual Shadow Maps
Materials & Shaders
Material Editor — node-based shader graph
Key output pins:
Base Color — albedo texture/color
Metallic — 0 = dielectric, 1 = metal
Roughness — 0 = mirror, 1 = diffuse
Normal — normal map
Emissive — self-illumination (drives bloom)
Opacity — transparency (Blend Mode: Translucent)
Ambient Occlusion — baked AO texture
Material Domains:
Surface — standard 3D surface
Deferred Decal — projected onto surfaces
Light Function — modulate light shape
Post Process — full-screen effect
UI — for UMG widgets
Material Instances:
Child of a Material — override parameters without recompile
Dynamic Material Instance (MID) — change params at runtime
// Create dynamic material instance at runtimeUMaterialInstanceDynamic* MID = UMaterialInstanceDynamic::Create(BaseMaterial, this);Mesh->SetMaterial(0, MID);MID->SetScalarParameterValue(TEXT("Roughness"), 0.3f);MID->SetVectorParameterValue(TEXT("Color"), FLinearColor::Red);MID->SetTextureParameterValue(TEXT("Albedo"), MyTexture);
Niagara Particle System
Overview
Niagara is UE5's GPU particle system (replaces Cascade).
Structure:
System — top-level asset, contains emitters
Emitter — defines particle behavior
Module — reusable behavior block (spawn rate, velocity, color)
Emitter update stages:
Emitter Spawn — runs once when emitter starts
Emitter Update — runs every frame
Particle Spawn — runs when each particle is born
Particle Update — runs every frame per particle
Render — how particles are drawn (sprite, mesh, ribbon)
Tags are hierarchical strings: "Status.Burning", "Ability.Jump", "Character.Dead"
Register in Project Settings → GameplayTags
Uses:
- Block abilities while stunned: block tag "Status.Stunned"
- Cancel abilities: cancel tag "Ability.Jump" cancels jump
- Trigger effects: GameplayCue.Explosion
- Query: HasMatchingGameplayTag, HasAllMatchingGameplayTags
World Building Tools
Landscape
Landscape — large outdoor terrain system
Workflow:
1. Create Landscape (Modes → Landscape → Manage → New)
2. Sculpt: raise, lower, smooth, flatten, erosion
3. Paint: layer materials (grass, rock, dirt, snow)
4. Foliage: scatter trees, rocks, grass automatically
Landscape Material:
- Layer blend node
- Each layer: albedo + normal + roughness
- Weight-painted in editor
Nanite Tessellation (UE5.1+):
- Displace landscape geometry at render time
- No pre-tessellation needed
World Partition (UE5 Open World)
World Partition replaces World Composition for large worlds.
Features:
- Automatic streaming — cells load/unload based on player position
- One persistent level — no manual sub-level management
- Data Layers — toggle content visibility (day/night, seasons)
- HLOD (Hierarchical LOD) — distant merged meshes
Setup:
World Settings → Enable World Partition
Set streaming distance per actor class
Stat commands (console ~ key):
stat fps — frame rate
stat unit — frame, game, draw, GPU times
stat game — gameplay tick times
stat scenerendering — draw calls, triangles
stat memory — memory usage
stat streaming — asset streaming info
Unreal Insights:
- Full frame profiler (CPU + GPU)
- Network profiling
- Memory tracking
Run: UnrealInsights.exe, launch game with -trace=cpu,gpu,memory
GPU Visualizer (Ctrl+Shift+,):
- Per-pass GPU timing breakdown
RenderDoc integration:
- Full GPU frame capture and analysis
Common Optimizations
Draw Calls:
- Merge static meshes (HLOD, Merge Actors tool)
- Use Instanced Static Mesh (ISM) for repeated objects
- Use Hierarchical ISM (HISM) for foliage
- Enable Nanite on high-poly static meshes
Tick:
- Disable tick on actors that don't need it
PrimaryActorTick.bCanEverTick = false;
- Reduce tick interval
PrimaryActorTick.TickInterval = 0.1f; // 10 times/sec
- Use timers instead of tick for infrequent updates
Memory:
- Stream assets (don't load everything upfront)
- Use Soft Object References for optional assets
- Pool frequently spawned actors
Shadows:
- Use Virtual Shadow Maps (VSM) — more efficient
- Limit dynamic shadow casters
- Use baked lightmaps for static geometry
Soft References & Async Loading
// Hard reference — loads immediately (avoid for large assets)UPROPERTY(EditDefaultsOnly)UTexture2D* Texture;// Soft reference — loads on demandUPROPERTY(EditDefaultsOnly)TSoftObjectPtr<UTexture2D> TextureSoft;// Async loadFStreamableManager& Streamable = UAssetManager::GetStreamableManager();Streamable.RequestAsyncLoad(TextureSoft.ToSoftObjectPath(), FStreamableDelegate::CreateUObject(this, &AMyActor::OnTextureLoaded));void AMyActor::OnTextureLoaded(){ UTexture2D* Tex = TextureSoft.Get(); Mesh->SetMaterial(0, CreateMaterialWithTexture(Tex));}
Useful Utilities & Helpers
UGameplayStatics
#include "Kismet/GameplayStatics.h"// Get playerAPlayerController* PC = UGameplayStatics::GetPlayerController(this, 0);APawn* Player = UGameplayStatics::GetPlayerPawn(this, 0);ACharacter* Char = UGameplayStatics::GetPlayerCharacter(this, 0);// Load levelUGameplayStatics::OpenLevel(this, FName("Level_02"));UGameplayStatics::OpenLevelBySoftObjectPtr(this, LevelRef);// Apply damageUGameplayStatics::ApplyDamage(TargetActor, 25.f, Controller, this, DamageType);UGameplayStatics::ApplyRadialDamage(this, 100.f, Center, 500.f, DamageType, {}, this, Controller);// Slow motionUGameplayStatics::SetGlobalTimeDilation(this, 0.2f);// Get all actors of classTArray<AActor*> Enemies;UGameplayStatics::GetAllActorsOfClass(GetWorld(), AEnemy::StaticClass(), Enemies);
UCLASS()class UMyAttributeSet : public UAttributeSet{ GENERATED_BODY()public: UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health) FGameplayAttributeData Health; ATTRIBUTE_ACCESSORS(UMyAttributeSet, Health) UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_MaxHealth) FGameplayAttributeData MaxHealth; ATTRIBUTE_ACCESSORS(UMyAttributeSet, MaxHealth) // Called before attribute change — clamp values here virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override { if (Attribute == GetHealthAttribute()) NewValue = FMath::Clamp(NewValue, 0.f, GetMaxHealth()); } // Called after GameplayEffect applied virtual void PostGameplayEffectExecute( const FGameplayEffectModCallbackData& Data) override;};
GameplayAbility
UCLASS()class UGA_FireWeapon : public UGameplayAbility{ GENERATED_BODY()public: UGA_FireWeapon() { // Ability can only be activated once at a time InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor; // Tag required on owner to activate ActivationRequiredTags.AddTag(FGameplayTag::RequestGameplayTag("State.Armed")); // Tag applied while active ActivationOwnedTags.AddTag(FGameplayTag::RequestGameplayTag("Ability.Firing")); } virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override { // Commit (check/consume cost + cooldown) if (!CommitAbility(Handle, ActorInfo, ActivationInfo)) { EndAbility(Handle, ActorInfo, ActivationInfo, true, true); return; } // Do the thing SpawnProjectile(); EndAbility(Handle, ActorInfo, ActivationInfo, true, false); }};
GameplayEffect
GameplayEffect types:
Instant — apply once (damage, instant heal)
Duration — apply for N seconds (burn, slow)
Infinite — apply until removed (passive buff, aura)
Modifiers:
Add, Multiply, Override, Divide
Target: specific attribute (Health, MoveSpeed)
Stacking:
AggregateBySource — each source has own stack
AggregateByTarget — all sources share one stack
Applying in C++:
FGameplayEffectContextHandle Context = ASC->MakeEffectContext();
FGameplayEffectSpecHandle Spec = ASC->MakeOutgoingSpec(
DamageEffectClass, Level, Context);
ASC->ApplyGameplayEffectSpecToTarget(*Spec.Data.Get(), TargetASC);
GameplayTags
// Define tags in DefaultGameplayTags.ini or via editor// Tags are hierarchical: "Ability.Fire" is child of "Ability"// Check tagif (ASC->HasMatchingGameplayTag( FGameplayTag::RequestGameplayTag("State.Dead"))){ ... }// Add/remove tagASC->AddLooseGameplayTag(FGameplayTag::RequestGameplayTag("State.Stunned"));ASC->RemoveLooseGameplayTag(FGameplayTag::RequestGameplayTag("State.Stunned"));// Tag containersFGameplayTagContainer Tags;Tags.AddTag(FGameplayTag::RequestGameplayTag("Ability.Fire"));bool bHasAny = ASC->HasAnyMatchingGameplayTags(Tags);
Materials & Shaders
Material Basics
Material — shader program defining surface appearance.
Material Instance — parameterized copy of a Material (fast, no recompile).
Material Function — reusable node subgraph.
Blend Modes:
Opaque — solid surface (default, cheapest)
Masked — binary transparency (foliage, fences)
Translucent — full alpha blend (glass, water, particles)
Additive — adds color to background (fire, glow)
Shading Models:
Default Lit — standard PBR
Unlit — no lighting (UI, emissive-only)
Subsurface — skin, wax, marble
Clear Coat — car paint, lacquer
Two Sided Foliage — leaves with back-face lighting
Hair — Kajiya-Kay hair shading
Eye — realistic eye rendering
PBR Inputs
Base Color — albedo (no lighting). RGB 0-1.
Metallic — 0 = dielectric, 1 = metal. Binary in practice.
Roughness — 0 = mirror, 1 = fully diffuse.
Specular — non-metal specular intensity (default 0.5).
Normal — tangent-space normal map (blue-ish).
Emissive — self-illumination. HDR values drive Bloom.
Ambient Occlusion — pre-baked crevice darkening.
Opacity — for Masked/Translucent modes.
World Position Offset — vertex displacement (cloth, water waves).
Material Nodes (Key)
Texture Sample — sample texture at UV
TextureCoordinate — UV channel (tiling, offset)
Panner — animate UVs (scrolling water, lava)
Rotator — rotate UVs
Lerp — blend between A and B by Alpha
Multiply / Add — math on colors/values
Fresnel — rim/edge glow effect
VertexColor — per-vertex color from mesh
WorldPosition — absolute world XYZ of pixel
CameraVector — direction from pixel to camera
Time — current game time (for animation)
Noise — procedural noise (Perlin, Voronoi, etc.)
BreakOutFloat3Components — split RGB into R, G, B
MakeFloat3 — combine R, G, B into RGB
Dynamic Material Instances
// Create dynamic instance at runtimeUMaterialInstanceDynamic* DynMat = UMaterialInstanceDynamic::Create(BaseMaterial, this);Mesh->SetMaterial(0, DynMat);// Set scalar parameterDynMat->SetScalarParameterValue(TEXT("Opacity"), 0.5f);// Set vector parameter (color)DynMat->SetVectorParameterValue(TEXT("EmissiveColor"), FLinearColor(1.f, 0.2f, 0.f));// Set texture parameterDynMat->SetTextureParameterValue(TEXT("DiffuseTexture"), MyTexture);
Niagara is UE5's particle/VFX system (replaces Cascade).
Hierarchy:
Niagara System — top-level asset, contains emitters
Niagara Emitter — one particle type (sparks, smoke, etc.)
Niagara Module — reusable logic block (Initialize, Update, Render)
Simulation stages:
Emitter Update — runs once per emitter per frame
Particle Spawn — runs when particle is born
Particle Update — runs every frame per particle
Event Handler — respond to collision/death events
Key Modules
Spawn Rate / Burst — how many particles, when
Initialize Particle — set initial position, velocity, color, size, lifetime
Add Velocity — constant or random velocity
Gravity Force — apply gravity
Drag — air resistance
Curl Noise Force — turbulent swirling motion
Collision — particles bounce off world geometry
Scale Color — fade in/out over lifetime
Scale Sprite Size — grow/shrink over lifetime
Sprite Renderer — render as camera-facing quad
Mesh Renderer — render as 3D mesh
Ribbon Renderer — connect particles as ribbon (trails)
Spawning from C++
#include "NiagaraFunctionLibrary.h"#include "NiagaraComponent.h"UPROPERTY(EditDefaultsOnly)UNiagaraSystem* ExplosionEffect;// Spawn at location (fire and forget)UNiagaraFunctionLibrary::SpawnSystemAtLocation( GetWorld(), ExplosionEffect, GetActorLocation());// Spawn attached (follows actor)UNiagaraComponent* NiagaraComp = UNiagaraFunctionLibrary::SpawnSystemAttached( ExplosionEffect, RootComponent, NAME_None, FVector::ZeroVector, FRotator::ZeroRotator, EAttachLocation::KeepRelativeOffset, true);// Set Niagara parameter from C++NiagaraComp->SetVariableFloat(TEXT("SpawnRate"), 100.f);NiagaraComp->SetVariableLinearColor(TEXT("Color"), FLinearColor::Red);NiagaraComp->SetVariableVec3(TEXT("EmitterVelocity"), Velocity);
GPU Simulation
CPU Simulation:
- Runs on CPU, flexible, supports full Blueprint/C++ interaction
- Max ~100k particles before performance issues
GPU Simulation:
- Runs entirely on GPU
- Millions of particles possible
- Limited interaction with CPU (no per-particle C++ callbacks)
- Enable: Emitter Properties → Sim Target → GPU Compute Sim
GPU Raytracing Particles:
- Enable in Project Settings for RT shadows on particles
Nanite — Virtualized Geometry
How Nanite Works
Nanite is UE5's virtualized micropolygon geometry system.
Traditional LOD problem:
- Artist creates LOD0 (high), LOD1, LOD2, LOD3 manually
- Engine switches between them based on distance
- Still limited by triangle budget per frame
Nanite solution:
- Mesh stored as hierarchical cluster DAG (Directed Acyclic Graph)
- At runtime: GPU selects exactly the right detail level per cluster
- Clusters are ~128 triangles each
- Only clusters covering ~1 pixel are rendered
- Result: billions of triangles, no manual LODs needed
Limitations:
- No skeletal mesh (static meshes only — use for environment, props)
- No world position offset (WPO) by default (UE5.1+ has limited WPO)
- No translucent/masked materials (opaque only)
- Requires DX12 / Vulkan / Metal
UE5.1+: Nanite Tessellation for landscapes
- Landscape → Details → Enable Nanite ✓
- Displacement maps drive actual geometry (not just normal maps)
Foliage with Nanite:
- Foliage Tool → Mesh → Enable Nanite
- Millions of foliage instances with full geometric detail
- Combine with WPO for wind animation (UE5.1+ WPO support)
Lumen — Dynamic Global Illumination
How Lumen Works
Lumen is UE5's fully dynamic GI and reflection system.
Two rendering paths:
Software Lumen (default):
- Uses Signed Distance Fields (SDF) of meshes
- Screen traces + SDF traces for GI
- Works on any DX11+ GPU
- Lower quality, faster
Hardware Lumen (Ray Tracing):
- Uses GPU ray tracing (RTX / RDNA2+)
- Higher quality reflections and GI
- Enable: Project Settings → Rendering → Lumen → Use Hardware Ray Tracing
Lumen covers:
- Indirect diffuse lighting (bounced light)
- Reflections (replaces reflection captures)
- Sky light (dynamic sky GI)
Lumen Settings
Project Settings → Rendering → Global Illumination:
Dynamic Global Illumination Method → Lumen
Reflection Method → Lumen
Post Process Volume:
Lumen Global Illumination:
Final Gather Quality — 1 (default) to 4 (high quality)
Scene Detail — affects SDF resolution
Lumen Reflections:
Quality — 1-4
Ray Lighting Mode — Surface Cache (fast) / Hit Lighting (accurate)
Console commands:
r.Lumen.DiffuseIndirect.Allow 1/0
r.Lumen.Reflections.Allow 1/0
r.Lumen.TraceMeshSDFs 1/0
Lumen Performance Tips
- Use Emissive materials to act as area lights (Lumen picks them up)
- Sky Atmosphere + Directional Light → Lumen sky GI works automatically
- Avoid too many small emissive meshes (expensive SDF updates)
- Use Lumen Scene Detail setting to balance quality vs performance
- For indoor scenes: place Sky Light with Lumen enabled
- Hardware Lumen: requires r.RayTracing 1 and DXR-capable GPU
- Lumen doesn't support translucent surfaces as GI emitters
Chaos Physics
Overview
Chaos is UE5's built-in physics engine (replaced PhysX in UE5).
Features:
Rigid body simulation — standard physics objects
Chaos Destruction — real-time fracture/destruction
Chaos Cloth — cloth simulation
Chaos Vehicles — wheeled vehicle physics
Chaos Flesh (UE5.1+) — soft body / muscle simulation
Chaos Destruction (Geometry Collections)
Workflow:
1. Select static mesh → Fracture Mode (toolbar)
2. Fracture: Uniform, Voronoi, Planar, Brick, Cluster
3. Generate Geometry Collection asset
4. Place in level → add Geometry Collection Component
5. Set Damage Threshold — how much force to trigger break
In C++:
Setup:
1. Skeletal mesh with cloth mesh section
2. Clothing Tool (editor) → paint cloth weights
Max Distance — how far vertex can move from animated position
Backstop — prevents cloth from penetrating body
3. Cloth Config: stiffness, damping, gravity scale, wind
In C++:
UClothingAssetBase* ClothAsset = SkeletalMesh->GetClothingAsset(0);
// Cloth simulates automatically when SkeletalMeshComponent ticks
World Partition replaces World Composition for open worlds.
How it works:
- Level is one large map (no sub-levels needed)
- World is divided into cells (configurable size, e.g., 128m x 128m)
- Cells stream in/out based on player position
- Each cell can have its own loading distance
Enable:
World Settings → World Partition → Enable World Partition ✓
HLOD (Hierarchical LOD):
- Distant cells replaced by simplified proxy meshes
- Auto-generated: World Partition → HLOD → Build HLODs
Data Layers:
- Tag actors with Data Layers (Day/Night, Quest states)
- Load/unload layers at runtime
Data Layers
// Load/unload data layer at runtime#include "WorldPartition/DataLayer/DataLayerSubsystem.h"UDataLayerSubsystem* DLS = GetWorld()->GetSubsystem<UDataLayerSubsystem>();// Set layer stateDLS->SetDataLayerRuntimeState(DayLayerAsset, EDataLayerRuntimeState::Activated);DLS->SetDataLayerRuntimeState(NightLayerAsset, EDataLayerRuntimeState::Unloaded);
PCG Framework (UE5.2+) — node-based procedural generation.
Use cases:
- Scatter foliage/rocks along splines
- Generate roads, rivers, paths
- Populate open worlds with props
- Runtime procedural level generation
Core concepts:
PCG Graph — node graph defining generation logic
PCG Component — attached to Actor, runs the graph
Point Data — set of 3D points with attributes (position, rotation, scale)
Attribute — custom data per point (type, density, etc.)
Key PCG Nodes
Get Spline Data — sample points along a spline
Get Landscape Data — sample landscape surface
Surface Sampler — scatter points on a surface
Density Filter — remove points by density/noise
Projection — project points onto surface
Static Mesh Spawner — spawn meshes at point positions
Transform Points — offset/rotate/scale points
Difference — subtract one point set from another
Intersection — keep only overlapping points
Attribute Operation — math on point attributes
Mass Entity is UE5's data-oriented ECS framework.
Used for: large crowds, flocks, traffic, thousands of AI agents.
Core concepts:
Entity — lightweight ID (no components directly)
Fragment — data struct (like ECS component)
Tag — zero-size marker fragment
Archetype — unique combination of fragments
Processor — system that queries and processes entities
EntityManager — owns all entities and archetypes
Plugins needed:
MassEntity, MassGameplay, MassAI, MassSpawner, ZoneGraph
Fragments & Processors
// Define a Fragment (pure data)USTRUCT()struct FMassVelocityFragment : public FMassFragment{ GENERATED_BODY() FVector Value = FVector::ZeroVector;};// Define a Processor (system)UCLASS()class UMassMovementProcessor : public UMassProcessor{ GENERATED_BODY()public: UMassMovementProcessor(); virtual void ConfigureQueries() override { // Query entities that have both Transform and Velocity EntityQuery.AddRequirement<FTransformFragment>( EMassFragmentAccess::ReadWrite); EntityQuery.AddRequirement<FMassVelocityFragment>( EMassFragmentAccess::ReadOnly); } virtual void Execute(FMassEntityManager& EntityManager, FMassExecutionContext& Context) override { EntityQuery.ForEachEntityChunk(EntityManager, Context, [](FMassExecutionContext& Ctx) { auto Transforms = Ctx.GetMutableFragmentView<FTransformFragment>(); auto Velocities = Ctx.GetFragmentView<FMassVelocityFragment>(); float DeltaTime = Ctx.GetDeltaTimeSeconds(); for (int32 i = 0; i < Ctx.GetNumEntities(); i++) { Transforms[i].GetMutableTransform().AddToTranslation( Velocities[i].Value * DeltaTime); } }); }};
Mass + Smart Objects + ZoneGraph
ZoneGraph:
- Defines lanes/paths for Mass agents to follow
- Replaces NavMesh for large-scale crowd movement
- Zones: roads, sidewalks, corridors
Smart Objects:
- Interactable world objects (bench, vending machine, door)
- Mass agents claim and interact with Smart Objects
- Handles concurrent access (only N agents at once)
MassSpawner:
- Spawns thousands of entities efficiently
- Configures entity templates (fragment sets)
- Integrates with World Partition for streaming
Advanced C++ Patterns
Subsystems
// Subsystems are auto-instanced singletons tied to a lifetime scope// Cleaner alternative to GameInstance variables or static singletons// Types:// UGameInstanceSubsystem — lives as long as GameInstance// UWorldSubsystem — lives as long as World// ULocalPlayerSubsystem — per local player// UEngineSubsystem — lives as long as engineUCLASS()class UInventorySubsystem : public UGameInstanceSubsystem{ GENERATED_BODY()public: virtual void Initialize(FSubsystemCollectionBase& Collection) override; virtual void Deinitialize() override; void AddItem(FName ItemID, int32 Count); int32 GetItemCount(FName ItemID) const;private: TMap<FName, int32> Inventory;};// Access from anywhere:UInventorySubsystem* Inv = GetGameInstance() ->GetSubsystem<UInventorySubsystem>();Inv->AddItem("Sword", 1);
Unreal Insights:
- Full-featured profiler (CPU, GPU, memory, networking)
- Launch: UnrealInsights.exe
- In game: -trace=cpu,gpu,memory,log
- Trace channels: CPU, GPU, Frame, Log, Bookmark, Object
Stat Commands (in-game console ~):
stat fps — FPS + frame time
stat unit — Game/Draw/GPU thread times
stat unitgraph — frame time graph
stat game — game thread breakdown
stat gpu — GPU pass breakdown
stat scenerendering — draw calls, triangles
stat memory — memory usage
stat streaming — asset streaming stats
stat particles — particle system stats
GPU Visualizer:
Ctrl+Shift+, (comma) — open GPU frame breakdown
CPU Optimization
Tick optimization:
- Disable tick on actors that don't need it:
PrimaryActorTick.bCanEverTick = false;
- Reduce tick interval:
PrimaryActorTick.TickInterval = 0.1f; // 10 times/sec
- Use timers instead of Tick for infrequent logic
Blueprint vs C++:
- Move hot-path Blueprint logic to C++
- Blueprint function calls have overhead (~10x vs C++)
Collision:
- Use simple collision shapes (capsule > convex > mesh)
- Disable complex collision on non-interactive meshes
- Use async line traces for non-critical queries
AI:
- Stagger AI updates (not all AI every frame)
- Use Mass Entity for large crowds
- Sleep distant AI (LOD AI system)
GPU Optimization
Draw Calls:
- Merge static meshes (HLOD, Merge Actors tool)
- Use Instanced Static Mesh (ISM) for repeated objects
- Use Hierarchical ISM (HISM) for foliage
- Nanite eliminates LOD draw call overhead
Shader complexity:
- View Mode → Shader Complexity (green=cheap, red=expensive)
- Reduce instruction count in hot materials
- Use Material LOD (simpler material at distance)
Overdraw:
- View Mode → Quad Overdraw
- Sort translucent objects back-to-front
- Use Depth Fade for soft particle edges (cheaper than full blend)
Texture:
- Use texture streaming (enabled by default)
- Set correct LOD Bias per texture
- Use texture atlases for small UI/decal textures
Memory Optimization
Asset audit:
- Window → Developer Tools → Asset Audit
- Find oversized textures, duplicate assets
Texture compression:
- Use BC7 for color, BC5 for normals, BC4 for grayscale
- Set max texture size per platform
Mesh:
- Remove unused UV channels
- Reduce vertex count on distant/small meshes
Memory tracking:
stat memory
memreport -full — detailed memory report to log
obj list class=Texture2D — list all loaded textures
Rendering Pipeline Internals
UE Rendering Architecture
Threads:
Game Thread — gameplay logic, actor ticks, Blueprint
Render Thread — builds render commands, manages scene proxy
RHI Thread — translates to DX12/Vulkan/Metal API calls
GPU — executes draw calls
Scene Proxy:
- Each UPrimitiveComponent has a FPrimitiveSceneProxy on render thread
- Game thread sends data via render commands (ENQUEUE_RENDER_COMMAND)
- Never access UObjects from render thread directly
Render passes (simplified):
1. PrePass (Depth) — early-Z for occlusion
2. Base Pass — GBuffer fill (deferred) or lit (forward)
3. Lighting — deferred lighting passes
4. Lumen GI — indirect lighting
5. Reflections — Lumen / SSR / reflection captures
6. Translucency — forward-rendered transparent objects
7. Post Processing — bloom, DOF, tone mapping, AA
8. UI — Slate / UMG rendered last
Every Actor has a Role and RemoteRole:
ROLE_Authority — server owns this actor (authoritative)
ROLE_SimulatedProxy — client simulates movement (other players)
ROLE_AutonomousProxy — client controls this actor (local player)
ROLE_None — not replicated
Check in C++:
HasAuthority() — true on server
IsLocallyControlled() — true on owning client
GetLocalRole() — this machine's role
GetRemoteRole() — other machine's role
Common pattern:
if (HasAuthority()) { /* server logic */ }
if (IsLocallyControlled()) { /* local player input */ }
Prediction & Reconciliation
UCharacterMovementComponent has built-in prediction:
- Client predicts movement locally
- Server validates and corrects
- Handles latency transparently
Custom prediction (advanced):
- Override PredictedMoveAbility in GAS
- Use FPredictionKey to correlate client/server actions
- Rollback state on misprediction
Network smoothing:
NetworkSmoothingMode:
Disabled — snap to server position
Linear — lerp to server position
Exponential — smooth exponential correction (default)
Iris Replication System (UE5.1+)
Iris is UE5's next-gen replication system (replaces legacy replication).
Key improvements:
- Batch replication (fewer RPCs, better bandwidth)
- Prioritization per connection
- Filtering (don't send irrelevant data to clients)
- Delta compression
Enable:
Project Settings → Network → Use Iris Replication System ✓
Iris ReplicationFragment (replaces GetLifetimeReplicatedProps):
- Define replication state as structs
- Automatic delta serialization
Dedicated Server Build
Build dedicated server:
UnrealBuildTool MyGame Win64 Development -Server
Server-only code:
#if UE_SERVER
// Only compiled in server builds
#endif
if (IsRunningDedicatedServer()) { ... }
Listen server vs Dedicated server:
Listen server — one player hosts + plays (peer hosting)
Dedicated server — headless server, no local player
Online Subsystem:
IOnlineSubsystem* OSS = IOnlineSubsystem::Get();
IOnlineSessionPtr Sessions = OSS->GetSessionInterface();
// Create/find/join sessions (Steam, EOS, NULL)
MetaHuman & Animation Advanced
MetaHuman
MetaHuman Creator — web-based photorealistic human creator.
Workflow:
1. Create at metahuman.unrealengine.com
2. Download via Quixel Bridge in UE editor
3. MetaHuman comes with:
- Full body skeletal mesh (LOD0-LOD3)
- Face rig with 330+ blend shapes
- Hair groom (Strand-based)
- Clothing meshes
- Animation Blueprint (face + body)
Performance:
LOD0 — ~80k triangles (cinematic, close-up)
LOD1 — ~30k triangles (gameplay)
LOD2 — ~10k triangles (background)
LOD3 — ~3k triangles (crowd)
Control Rig
Control Rig — procedural animation system in UE5.
Use cases:
- Full-body IK (FBIK)
- Procedural secondary motion (tail, ears, cloth)
- Custom rig controls for animators
- Runtime deformation (muscle bulge, squash/stretch)
Key nodes:
FABRIK — Forward And Backward Reaching IK
CCDIK — Cyclic Coordinate Descent IK
Spline IK — spine/tail along spline
Look At — bone tracks target
Point At — aim constraint
Twist Corrective — fix elbow/knee twist artifacts
Motion Matching (UE5.3+)
Motion Matching — data-driven animation selection.
Replaces hand-crafted state machines with pose search.
How it works:
1. Large animation database (mocap clips)
2. Each frame: search database for best matching pose
based on: current pose + desired trajectory
3. Blend to best match
Result:
- Natural transitions without explicit state machine
- Handles complex locomotion (turns, starts, stops)
- Used in Fortnite Chapter 4+
Setup:
- PoseSearch plugin (enable in plugins)
- Create PoseSearchDatabase asset
- Add animation clips
- Use MotionMatching node in Anim Graph
Sequencer (Cinematics)
Sequencer — UE's non-linear animation/cinematic editor.
Track types:
Actor Track — animate any actor property
Camera Cut Track — switch between cameras
Skeletal Animation — play animation clips on characters
Audio Track — sync audio to sequence
Event Track — fire Blueprint events at specific frames
Fade Track — fade in/out
Level Visibility — show/hide levels
In C++:
// Play sequence from C++#include "LevelSequencePlayer.h"UPROPERTY(EditDefaultsOnly)ULevelSequence* CinematicSequence;void AMyGameMode::PlayCinematic(){ ALevelSequenceActor* SeqActor; ULevelSequencePlayer* Player = ULevelSequencePlayer::CreateLevelSequencePlayer( GetWorld(), CinematicSequence, FMovieSceneSequencePlaybackSettings(), SeqActor); Player->Play();}
// UE Interface — cleaner than Cast for interactionUINTERFACE(MinimalAPI, BlueprintType)class UInteractable : public UInterface{ GENERATED_BODY()};class IInteractable{ GENERATED_BODY()public: UFUNCTION(BlueprintNativeEvent, BlueprintCallable) void Interact(APlayerCharacter* Interactor); UFUNCTION(BlueprintNativeEvent, BlueprintCallable) FText GetInteractPrompt();};// Implement on any Actor:class AChest : public AActor, public IInteractable{ void Interact_Implementation(APlayerCharacter* Interactor) override { OpenChest(); }};// Call without knowing exact type:if (HitActor->Implements<UInteractable>()){ IInteractable::Execute_Interact(HitActor, PlayerCharacter);}
Debug Helpers
// Draw debug shapes (editor + PIE only in shipping builds)#include "DrawDebugHelpers.h"DrawDebugLine(World, Start, End, FColor::Red, false, 2.f, 0, 2.f);DrawDebugSphere(World, Center, Radius, 12, FColor::Green, false, 2.f);DrawDebugBox(World, Center, Extent, FColor::Blue, false, 2.f);DrawDebugCapsule(World, Center, HalfHeight, Radius, FQuat::Identity, FColor::Yellow, false, 2.f);DrawDebugString(World, Location, TEXT("Hello"), nullptr, FColor::White, 2.f);DrawDebugDirectionalArrow(World, Start, End, 50.f, FColor::Cyan, false, 2.f);// Conditional debug (only in non-shipping)#if !UE_BUILD_SHIPPING DrawDebugSphere(GetWorld(), GetActorLocation(), 50.f, 8, FColor::Red, false, -1.f);#endif
Packaging & Shipping
Build Configurations
Debug — full debug info, no optimization. Slow.
DebugGame — engine optimized, game code debug. Good for gameplay debugging.
Development — optimized, some debug info. Default for development.
Shipping — fully optimized, no debug. For release builds.
Test — like Shipping but with some profiling enabled.
Build targets:
Editor — runs in UE editor
Game — standalone game
Server — dedicated server (no rendering)
Client — client-only (no server code)
Packaging
Package project:
Platforms → Windows → Package Project
or: File → Package Project → [Platform]
Key settings (Project Settings → Packaging):
Build Configuration → Shipping (for release)
Cook only maps → list maps to include
Compress content → smaller package size
Use Pak File → bundle assets into .pak
Encrypt Pak → protect assets
Command line packaging:
RunUAT.bat BuildCookRun
-project="MyGame.uproject"
-platform=Win64
-configuration=Shipping
-cook -build -stage -pak -archive
-archivedirectory="D:/Build"
Platform-Specific
Console (PS5/Xbox):
- Requires platform SDK + dev kit
- NDA with Sony/Microsoft required
- Epic provides platform-specific plugins
Mobile (iOS/Android):
- Android: requires Android Studio + NDK
- iOS: requires Mac + Xcode + Apple Developer account
- Use Mobile Preview in editor for quick testing
- Reduce texture sizes, disable Lumen/Nanite for mobile
- Use Forward Rendering for mobile (better performance)
VR/XR:
- Enable XR plugin (OpenXR, Oculus, SteamVR)
- Use VR Preview in editor
- Target 90Hz (11ms frame budget)
- Use Instanced Stereo Rendering
- Disable expensive post-process (DOF, motion blur)
Testing & Automation
Automation Testing
// Unit test with UE Automation Framework#include "Misc/AutomationTest.h"IMPLEMENT_SIMPLE_AUTOMATION_TEST(FMyMathTest, "MyGame.Math.VectorNormalize", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter)bool FMyMathTest::RunTest(const FString& Parameters){ FVector v(3.f, 4.f, 0.f); FVector normalized = v.GetSafeNormal(); TestEqual("Length should be 1", normalized.Size(), 1.f, 0.001f); TestTrue("X should be 0.6", FMath::IsNearlyEqual(normalized.X, 0.6f)); TestTrue("Y should be 0.8", FMath::IsNearlyEqual(normalized.Y, 0.8f)); return true;}// Run tests:// Session Frontend → Automation tab// or: -ExecCmds="Automation RunTests MyGame"
Functional Tests
Functional Test Actor — place in level, runs gameplay tests.
1. Place AFunctionalTest actor in test level
2. Override StartTest() in Blueprint or C++
3. Use AssertEqual, AssertTrue, FinishTest(Success/Failed)
Good for:
- Testing gameplay mechanics in context
- Regression testing level setups
- CI/CD integration
Gauntlet (CI Testing)
Gauntlet — UE's automated test framework for CI/CD.
Runs tests on:
- Multiple platforms simultaneously
- Dedicated server + client configurations
- Performance benchmarks
Integration:
RunUAT.bat RunUnreal
-project=MyGame.uproject
-platform=Win64
-configuration=Development
-test=MyGame.FunctionalTests