添加 claude code game studios 到项目

This commit is contained in:
panw
2026-05-15 14:52:29 +08:00
parent dff559462d
commit a16fe4bff7
415 changed files with 78609 additions and 0 deletions

View File

@@ -0,0 +1,292 @@
# Unreal Engine 5.7 — Animation Module Reference
**Last verified:** 2026-02-13
**Knowledge Gap:** UE 5.7 animation authoring improvements, Control Rig 2.0
---
## Overview
UE 5.7 animation systems:
- **Animation Blueprint**: State machine-based animation logic
- **Control Rig**: Runtime procedural animation (production-ready in UE5)
- **IK Rig + Retargeter**: Modern retargeting system
- **Sequencer**: Cinematic animation
---
## Animation Blueprint
### Create Animation Blueprint
1. Content Browser > Right Click > Animation > Animation Blueprint
2. Select parent class: `AnimInstance`
3. Select skeleton
### Animation State Machine
```cpp
// In Animation Blueprint Event Graph:
// - State Machine drives animation states (Idle, Walk, Run, Jump)
// - Blend Spaces for directional movement
// Access in C++:
UAnimInstance* AnimInstance = Mesh->GetAnimInstance();
AnimInstance->Montage_Play(AttackMontage);
```
---
## Play Animation Montages
### Animation Montage
```cpp
// Play montage
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
AnimInstance->Montage_Play(AttackMontage, 1.0f);
// Stop montage
AnimInstance->Montage_Stop(0.2f, AttackMontage);
// Check if montage is playing
bool bIsPlaying = AnimInstance->Montage_IsPlaying(AttackMontage);
```
### Montage Notify Events
```cpp
// Add notify event in Animation Montage (right-click timeline > Add Notify > New Notify)
// Implement in C++:
UCLASS()
class UMyAnimInstance : public UAnimInstance {
GENERATED_BODY()
public:
UFUNCTION()
void AnimNotify_AttackHit() {
// Called when notify is reached
DealDamage();
}
};
```
---
## Blend Spaces
### 1D Blend Space (Speed Blending)
```cpp
// Create: Content Browser > Animation > Blend Space 1D
// Horizontal Axis: Speed (0 = Idle, 1 = Walk, 2 = Run)
// Add animations at key points
// Use in Anim Blueprint:
// - Get speed from character
// - Feed into Blend Space
```
### 2D Blend Space (Directional Movement)
```cpp
// Create: Content Browser > Animation > Blend Space
// Horizontal Axis: Direction X (-1 to 1)
// Vertical Axis: Direction Y (-1 to 1)
// Place animations (Fwd, Back, Left, Right, diagonal)
```
---
## Control Rig (Procedural Animation)
### Create Control Rig
1. Content Browser > Animation > Control Rig
2. Select skeleton
3. Build rig hierarchy (bones, controls, IK)
### Use Control Rig in Animation Blueprint
```cpp
// Add "Control Rig" node to Anim Blueprint
// Assign Control Rig asset
// Procedurally modify bones at runtime
```
### Control Rig in C++
```cpp
// Get control rig component
UControlRig* ControlRig = /* Get from animation instance */;
// Set control value
ControlRig->SetControlValue<FVector>(TEXT("IK_Hand_R"), TargetLocation);
```
---
## IK Rig & Retargeting (UE5)
### Create IK Rig
1. Content Browser > Animation > IK Rig
2. Select skeleton
3. Add IK goals (hands, feet)
4. Set up solver chains
### Retarget Animations
1. Create IK Rig for source skeleton
2. Create IK Rig for target skeleton
3. Create IK Retargeter asset
4. Assign source and target IK Rigs
5. Batch retarget animations
### Retargeting in C++
```cpp
// Retargeting is primarily editor-based
// Animations are retargeted once, then used normally
```
---
## Animation Notify States
### Custom Notify State (Duration-Based Events)
```cpp
UCLASS()
class UAnimNotifyState_Invulnerable : public UAnimNotifyState {
GENERATED_BODY()
public:
virtual void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration, const FAnimNotifyEventReference& EventReference) override {
// Start invulnerability
AMyCharacter* Character = Cast<AMyCharacter>(MeshComp->GetOwner());
Character->bIsInvulnerable = true;
}
virtual void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, const FAnimNotifyEventReference& EventReference) override {
// End invulnerability
AMyCharacter* Character = Cast<AMyCharacter>(MeshComp->GetOwner());
Character->bIsInvulnerable = false;
}
};
```
---
## Skeletal Mesh & Sockets
### Attach Objects to Sockets
```cpp
// Create socket in Skeletal Mesh Editor (Skeleton Tree > Add Socket)
// Attach component to socket
UStaticMeshComponent* Weapon = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Weapon"));
Weapon->SetupAttachment(GetMesh(), TEXT("hand_r_socket"));
```
---
## Animation Curves
### Use Animation Curves
```cpp
// Add curve to animation:
// Animation Editor > Curves > Add Curve
// Read curve value in Anim Blueprint or C++:
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
float CurveValue = AnimInstance->GetCurveValue(TEXT("MyCurve"));
```
---
## Root Motion
### Enable Root Motion
```cpp
// In Animation Sequence: Asset Details > Root Motion > Enable Root Motion
// In Character class:
GetCharacterMovement()->bAllowPhysicsRotationDuringAnimRootMotion = true;
```
---
## Animation Layers (Linked Anim Graphs)
### Use Linked Anim Layers
```cpp
// Create separate Anim Blueprints for layers (e.g., upper body, lower body)
// Link in main Anim Blueprint: Add "Linked Anim Graph" node
// Dynamically switch layers:
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
AnimInstance->LinkAnimClassLayers(NewLayerClass);
```
---
## Sequencer (Cinematic Animation)
### Create Sequence
1. Content Browser > Cinematics > Level Sequence
2. Add tracks: Camera, Character, Animation, etc.
### Play Sequence from C++
```cpp
#include "LevelSequenceActor.h"
#include "LevelSequencePlayer.h"
ALevelSequenceActor* SequenceActor = /* Spawn or find in level */;
SequenceActor->GetSequencePlayer()->Play();
```
---
## Performance Tips
### Animation Optimization
```cpp
// LOD (Level of Detail) for skeletal meshes
// Reduce bone count for distant characters
// Anim Blueprint optimization:
// - Use "Anim Node Relevancy" (skip updates when not visible)
// - Disable updates when off-screen:
GetMesh()->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::OnlyTickPoseWhenRendered;
```
---
## Debugging
### Animation Debug Visualization
```cpp
// Console commands:
// showdebug animation - Show animation state info
// a.VisualizeSkeletalMeshBones 1 - Show skeleton bones
// Draw debug bones:
DrawDebugCoordinateSystem(GetWorld(), BoneLocation, BoneRotation, 50.0f, false, -1.0f, 0, 2.0f);
```
---
## Sources
- https://docs.unrealengine.com/5.7/en-US/animation-in-unreal-engine/
- https://docs.unrealengine.com/5.7/en-US/control-rig-in-unreal-engine/
- https://docs.unrealengine.com/5.7/en-US/ik-rig-in-unreal-engine/

View File

@@ -0,0 +1,289 @@
# Unreal Engine 5.7 — Audio Module Reference
**Last verified:** 2026-02-13
**Knowledge Gap:** UE 5.7 MetaSounds production-ready
---
## Overview
UE 5.7 audio systems:
- **MetaSounds**: Node-based procedural audio (RECOMMENDED, production-ready)
- **Sound Cues**: Legacy node-based audio (use for simple cases)
- **Audio Component**: Play sounds on actors
---
## Basic Audio Playback
### Play Sound at Location
```cpp
#include "Kismet/GameplayStatics.h"
// ✅ Play 2D sound (no spatialization)
UGameplayStatics::PlaySound2D(GetWorld(), ExplosionSound);
// ✅ Play sound at location (3D spatial audio)
UGameplayStatics::PlaySoundAtLocation(GetWorld(), ExplosionSound, GetActorLocation());
// ✅ With volume and pitch
UGameplayStatics::PlaySoundAtLocation(GetWorld(), ExplosionSound, GetActorLocation(), 0.7f, 1.2f);
```
---
## Audio Component
### Audio Component (Persistent Sound)
```cpp
// Create audio component
UAudioComponent* AudioComp = CreateDefaultSubobject<UAudioComponent>(TEXT("Audio"));
AudioComp->SetupAttachment(RootComponent);
AudioComp->SetSound(LoopingAmbience);
// Play/Stop
AudioComp->Play();
AudioComp->Stop();
// Fade in/out
AudioComp->FadeIn(2.0f); // 2 seconds
AudioComp->FadeOut(1.5f, 0.0f); // 1.5s to volume 0
// Adjust volume/pitch
AudioComp->SetVolumeMultiplier(0.5f);
AudioComp->SetPitchMultiplier(1.2f);
```
---
## 3D Spatial Audio
### Attenuation Settings
```cpp
// Create Sound Attenuation asset:
// Content Browser > Sounds > Sound Attenuation
// Configure:
// - Attenuation Shape: Sphere, Capsule, Box, Cone
// - Falloff Distance: Distance where sound becomes inaudible
// - Attenuation Function: Linear, Logarithmic, Inverse, etc.
// Assign in C++:
AudioComp->AttenuationSettings = AttenuationAsset;
```
### Attenuation Override in Code
```cpp
FSoundAttenuationSettings AttenuationOverride;
AttenuationOverride.AttenuationShape = EAttenuationShape::Sphere;
AttenuationOverride.FalloffDistance = 1000.0f;
AttenuationOverride.AttenuationShapeExtents = FVector(1000.0f);
AudioComp->AttenuationOverrides = AttenuationOverride;
AudioComp->bOverrideAttenuation = true;
```
---
## MetaSounds (Procedural Audio)
### Create MetaSound Source
1. Content Browser > Sounds > MetaSound Source
2. Open MetaSound editor
3. Build node graph:
- **Inputs**: Triggers, parameters
- **Generators**: Oscillators, noise, samples
- **Modulators**: Envelopes, LFOs
- **Effects**: Filters, reverb, delay
- **Output**: Audio output
### Play MetaSound
```cpp
// Play MetaSound like any sound
UGameplayStatics::PlaySound2D(GetWorld(), MetaSoundSource);
// Or with Audio Component
AudioComp->SetSound(MetaSoundSource);
AudioComp->Play();
```
### Set MetaSound Parameters
```cpp
// Define parameter in MetaSound (Input node with exposed parameter)
// Set parameter in C++:
AudioComp->SetFloatParameter(FName("Volume"), 0.8f);
AudioComp->SetIntParameter(FName("OctaveShift"), 2);
AudioComp->SetBoolParameter(FName("EnableReverb"), true);
```
---
## Sound Cues (Legacy)
### Create Sound Cue
1. Content Browser > Sounds > Sound Cue
2. Open Sound Cue editor
3. Add nodes: Random, Modulator, Mixer, etc.
### Use Sound Cue
```cpp
// Play like any sound
UGameplayStatics::PlaySound2D(GetWorld(), SoundCue);
```
---
## Sound Classes & Sound Mixes
### Sound Class (Volume Groups)
```cpp
// Create Sound Class: Content Browser > Sounds > Sound Class
// Hierarchy: Master > Music, SFX, Dialogue
// Assign to sound asset:
// Sound Wave > Sound Class = SFX
// Set volume in C++:
UAudioSettings* AudioSettings = GetMutableDefault<UAudioSettings>();
// Configure via Sound Class hierarchy
```
### Sound Mix (Dynamic Mixing)
```cpp
// Create Sound Mix asset
// Define adjustments: Lower music during dialogue, etc.
// Push sound mix
UGameplayStatics::PushSoundMixModifier(GetWorld(), DuckedMusicMix);
// Pop sound mix
UGameplayStatics::PopSoundMixModifier(GetWorld(), DuckedMusicMix);
```
---
## Audio Occlusion & Reverb
### Audio Occlusion (Walls Block Sound)
```cpp
// Enable in Audio Component:
AudioComp->bEnableOcclusion = true;
// Requires geometry with collision
```
### Reverb Volumes
```cpp
// Add Audio Volume to level (Volumes > Audio Volume)
// Configure reverb settings in Details panel
// Audio component automatically picks up reverb when inside volume
```
---
## Common Patterns
### Footstep Sounds (Random Variation)
```cpp
// Use Sound Cue with Random node, or:
UPROPERTY(EditAnywhere, Category = "Audio")
TArray<TObjectPtr<USoundBase>> FootstepSounds;
void PlayFootstep() {
int32 Index = FMath::RandRange(0, FootstepSounds.Num() - 1);
UGameplayStatics::PlaySoundAtLocation(GetWorld(), FootstepSounds[Index], GetActorLocation());
}
```
### Music Crossfade
```cpp
UAudioComponent* MusicA;
UAudioComponent* MusicB;
void CrossfadeMusic(float Duration) {
MusicA->FadeOut(Duration, 0.0f);
MusicB->FadeIn(Duration);
}
```
### Check if Sound is Playing
```cpp
if (AudioComp->IsPlaying()) {
// Sound is playing
}
```
---
## Audio Concurrency
### Limit Concurrent Sounds
```cpp
// Create Sound Concurrency asset:
// Content Browser > Sounds > Sound Concurrency
// Configure:
// - Max Count: Maximum instances of this sound
// - Resolution Rule: Stop Oldest, Stop Quietest, etc.
// Assign to sound:
// Sound Wave > Concurrency Settings
```
---
## Performance Tips
### Audio Optimization
```cpp
// Compression settings (Sound Wave asset):
// - Compression Quality: 40 (balance quality/size)
// - Streaming: Enable for large files (music)
// Reduce audio mixing cost:
// - Limit concurrent sounds via Sound Concurrency
// - Use simple attenuation shapes
// Disable audio for distant actors:
if (Distance > MaxAudibleDistance) {
AudioComp->Stop();
}
```
---
## Debugging
### Audio Debug Commands
```cpp
// Console commands:
// au.Debug.Sounds 1 - Show active sounds
// au.3dVisualize.Enabled 1 - Visualize 3D audio
// stat soundwaves - Show sound statistics
// stat soundmixes - Show active sound mixes
```
---
## Sources
- https://docs.unrealengine.com/5.7/en-US/audio-in-unreal-engine/
- https://docs.unrealengine.com/5.7/en-US/metasounds-in-unreal-engine/

View File

@@ -0,0 +1,288 @@
# Unreal Engine 5.7 — Input Module Reference
**Last verified:** 2026-02-13
**Knowledge Gap:** UE 5.7 uses Enhanced Input as default (legacy input deprecated)
---
## Overview
UE 5.7 input systems:
- **Enhanced Input** (RECOMMENDED, default in UE5): Modular, rebindable, context-based
- **Legacy Input**: Deprecated, avoid for new projects
---
## Enhanced Input System
### Setup Enhanced Input
1. **Enable Plugin**: `Edit > Plugins > Enhanced Input` (enabled by default in UE5)
2. **Project Settings**: `Engine > Input > Default Classes > Default Player Input Class = EnhancedPlayerInput`
---
### Create Input Actions
1. Content Browser > Input > Input Action
2. Name it (e.g., `IA_Jump`, `IA_Move`)
3. Configure:
- **Value Type**: Digital (bool), Axis1D (float), Axis2D (Vector2D), Axis3D (Vector)
Example Input Actions:
- `IA_Jump`: Digital (bool)
- `IA_Move`: Axis2D (Vector2D)
- `IA_Look`: Axis2D (Vector2D)
- `IA_Fire`: Digital (bool)
---
### Create Input Mapping Context
1. Content Browser > Input > Input Mapping Context
2. Name it (e.g., `IMC_Default`)
3. Add mappings:
- `IA_Jump` → Space Bar
- `IA_Move` → W/A/S/D keys (combine X/Y)
- `IA_Look` → Mouse XY
- `IA_Fire` → Left Mouse Button
---
### Bind Input in C++
```cpp
#include "EnhancedInputComponent.h"
#include "EnhancedInputSubsystems.h"
#include "InputActionValue.h"
class AMyCharacter : public ACharacter {
public:
// Input Actions (assign in Blueprint)
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> MoveAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> LookAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputAction> JumpAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Input")
TObjectPtr<UInputMappingContext> DefaultMappingContext;
protected:
virtual void BeginPlay() override {
Super::BeginPlay();
// Add Input Mapping Context
if (APlayerController* PC = Cast<APlayerController>(Controller)) {
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer())) {
Subsystem->AddMappingContext(DefaultMappingContext, 0);
}
}
}
virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override {
Super::SetupPlayerInputComponent(PlayerInputComponent);
UEnhancedInputComponent* EIC = Cast<UEnhancedInputComponent>(PlayerInputComponent);
if (EIC) {
// Bind actions
EIC->BindAction(JumpAction, ETriggerEvent::Started, this, &ACharacter::Jump);
EIC->BindAction(JumpAction, ETriggerEvent::Completed, this, &ACharacter::StopJumping);
EIC->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMyCharacter::Move);
EIC->BindAction(LookAction, ETriggerEvent::Triggered, this, &AMyCharacter::Look);
}
}
void Move(const FInputActionValue& Value) {
FVector2D MoveVector = Value.Get<FVector2D>();
if (Controller) {
AddMovementInput(GetActorForwardVector(), MoveVector.Y);
AddMovementInput(GetActorRightVector(), MoveVector.X);
}
}
void Look(const FInputActionValue& Value) {
FVector2D LookVector = Value.Get<FVector2D>();
if (Controller) {
AddControllerYawInput(LookVector.X);
AddControllerPitchInput(LookVector.Y);
}
}
};
```
---
## Input Triggers
### Trigger Types
Input Actions can have triggers to control when they fire:
- **Pressed**: When input starts
- **Released**: When input ends
- **Hold**: Hold for duration
- **Tap**: Quick press
- **Pulse**: Repeated firing while held
### Add Trigger in Editor
1. Open Input Action asset
2. Triggers > Add > Select trigger type (e.g., `Hold`)
3. Configure (e.g., Hold Time = 0.5s)
---
## Input Modifiers
### Modifier Types
Modifiers transform input values:
- **Negate**: Flip sign (-1 ↔ 1)
- **Dead Zone**: Ignore small inputs
- **Scalar**: Multiply by value
- **Smooth**: Smoothing over time
### Add Modifier in Editor
1. Open Input Action asset
2. Modifiers > Add > Select modifier (e.g., `Negate`)
3. Configure
---
## Input Mapping Contexts (Context Switching)
### Multiple Contexts
```cpp
// Define contexts
UPROPERTY(EditAnywhere, Category = "Input")
TObjectPtr<UInputMappingContext> DefaultContext;
UPROPERTY(EditAnywhere, Category = "Input")
TObjectPtr<UInputMappingContext> VehicleContext;
// Switch context
void EnterVehicle() {
if (APlayerController* PC = Cast<APlayerController>(Controller)) {
if (UEnhancedInputLocalPlayerSubsystem* Subsystem =
ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PC->GetLocalPlayer())) {
Subsystem->RemoveMappingContext(DefaultContext);
Subsystem->AddMappingContext(VehicleContext, 0);
}
}
}
```
---
## Legacy Input (Deprecated)
### Legacy Input Bindings
```cpp
// ❌ DEPRECATED: Do not use for new projects
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) {
// Legacy action binding
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
// Legacy axis binding
PlayerInputComponent->BindAxis("MoveForward", this, &AMyCharacter::MoveForward);
}
void MoveForward(float Value) {
AddMovementInput(GetActorForwardVector(), Value);
}
```
**Migration:** Use Enhanced Input instead.
---
## Gamepad Input
### Gamepad with Enhanced Input
```cpp
// Input Mapping Context:
// - IA_Move → Gamepad Left Thumbstick
// - IA_Look → Gamepad Right Thumbstick
// - IA_Jump → Gamepad Face Button Bottom (A/Cross)
// No code changes needed, just add gamepad mappings to Input Mapping Context
```
---
## Touch Input (Mobile)
### Touch Input with Enhanced Input
```cpp
// Input Mapping Context:
// - IA_Move → Touch (virtual thumbstick)
// - IA_Look → Touch (swipe)
// Use Touch Interface asset for virtual controls
```
---
## Rebinding Input at Runtime
### Change Key Mapping
```cpp
#include "PlayerMappableInputConfig.h"
// Get subsystem
UEnhancedInputLocalPlayerSubsystem* Subsystem = /* Get subsystem */;
// Get player mappable keys
FPlayerMappableKeySlot KeySlot = FPlayerMappableKeySlot(/*..*/);
FKey NewKey = EKeys::F; // Rebind to F key
// Apply new mapping
Subsystem->AddPlayerMappedKey(/*..*/);
```
---
## Input Debugging
### Debug Input
```cpp
// Console commands:
// showdebug input - Show input debug info
// Log input values:
UE_LOG(LogTemp, Warning, TEXT("Move Input: %s"), *MoveVector.ToString());
```
---
## Common Patterns
### Check if Key Pressed (Quick & Dirty)
```cpp
// For debugging only (not recommended for gameplay)
if (GetWorld()->GetFirstPlayerController()->IsInputKeyDown(EKeys::SpaceBar)) {
// Space bar is down
}
```
---
## Sources
- https://docs.unrealengine.com/5.7/en-US/enhanced-input-in-unreal-engine/
- https://docs.unrealengine.com/5.7/en-US/enhanced-input-action-and-input-mapping-context-in-unreal-engine/

View File

@@ -0,0 +1,338 @@
# Unreal Engine 5.7 — Navigation Module Reference
**Last verified:** 2026-02-13
**Knowledge Gap:** UE 5.7 navigation improvements
---
## Overview
UE 5.7 navigation systems:
- **Nav Mesh**: Automatic pathfinding mesh for AI
- **AI Controller**: Controls AI movement and behavior
- **Behavior Trees**: AI decision-making (covered in AI module)
---
## Nav Mesh Setup
### Add Nav Mesh Bounds Volume
1. Place Actors > Volumes > Nav Mesh Bounds Volume
2. Scale to cover walkable areas
3. Press `P` to toggle Nav Mesh visualization (green overlay)
### Nav Mesh Settings
```cpp
// Project Settings > Engine > Navigation System
// - Generate Navigation Only Around Navigation Invokers: Performance optimization
// - Auto Update Enabled: Rebuild NavMesh when geometry changes
```
---
## AI Controller & Movement
### Create AI Controller
```cpp
UCLASS()
class AEnemyAIController : public AAIController {
GENERATED_BODY()
public:
void BeginPlay() override {
Super::BeginPlay();
// Move to location
FVector TargetLocation = FVector(1000, 0, 0);
MoveToLocation(TargetLocation);
}
};
```
### Assign AI Controller to Pawn
```cpp
UCLASS()
class AEnemyCharacter : public ACharacter {
GENERATED_BODY()
public:
AEnemyCharacter() {
// ✅ Assign AI Controller class
AIControllerClass = AEnemyAIController::StaticClass();
AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
}
};
```
---
## Basic AI Movement
### Move to Location
```cpp
AAIController* AIController = Cast<AAIController>(GetController());
if (AIController) {
FVector TargetLocation = FVector(1000, 0, 0);
EPathFollowingRequestResult::Type Result = AIController->MoveToLocation(TargetLocation);
if (Result == EPathFollowingRequestResult::RequestSuccessful) {
UE_LOG(LogTemp, Warning, TEXT("Moving to location"));
}
}
```
### Move to Actor
```cpp
AActor* Target = /* Get target actor */;
AIController->MoveToActor(Target, 100.0f); // Stop 100 units away
```
### Stop Movement
```cpp
AIController->StopMovement();
```
---
## Path Following Events
### On Move Completed
```cpp
UCLASS()
class AEnemyAIController : public AAIController {
GENERATED_BODY()
public:
void BeginPlay() override {
Super::BeginPlay();
// Bind to move completed event
ReceiveMoveCompleted.AddDynamic(this, &AEnemyAIController::OnMoveCompleted);
}
UFUNCTION()
void OnMoveCompleted(FAIRequestID RequestID, EPathFollowingResult::Type Result) {
if (Result == EPathFollowingResult::Success) {
UE_LOG(LogTemp, Warning, TEXT("Reached destination"));
} else {
UE_LOG(LogTemp, Warning, TEXT("Failed to reach destination"));
}
}
};
```
---
## Pathfinding Queries
### Find Path to Location
```cpp
#include "NavigationSystem.h"
#include "NavigationPath.h"
UNavigationSystemV1* NavSys = UNavigationSystemV1::GetCurrent(GetWorld());
if (NavSys) {
FVector Start = GetActorLocation();
FVector End = TargetLocation;
FPathFindingQuery Query;
Query.StartLocation = Start;
Query.EndLocation = End;
Query.NavData = NavSys->GetDefaultNavDataInstance();
FPathFindingResult Result = NavSys->FindPathSync(Query);
if (Result.IsSuccessful()) {
UNavigationPath* NavPath = Result.Path.Get();
// Use path points: NavPath->GetPathPoints()
}
}
```
### Check if Location is Reachable
```cpp
UNavigationSystemV1* NavSys = UNavigationSystemV1::GetCurrent(GetWorld());
FNavLocation OutLocation;
bool bReachable = NavSys->ProjectPointToNavigation(TargetLocation, OutLocation);
if (bReachable) {
UE_LOG(LogTemp, Warning, TEXT("Location is reachable"));
}
```
---
## Nav Mesh Modifiers
### Nav Modifier Volume (Block/Allow Areas)
1. Place Actors > Volumes > Nav Modifier Volume
2. Configure Area Class (e.g., NavArea_Null to block, NavArea_LowHeight for crouching)
---
## Custom Nav Areas
### Create Custom Nav Area
```cpp
UCLASS()
class UNavArea_Jump : public UNavArea {
GENERATED_BODY()
public:
UNavArea_Jump() {
DefaultCost = 10.0f; // Higher cost = AI avoids unless necessary
FixedAreaEnteringCost = 100.0f; // One-time cost to enter
}
};
```
### Use Custom Nav Area
```cpp
// Assign to Nav Modifier Volume or geometry
```
---
## Nav Mesh Generation
### Rebuild Nav Mesh at Runtime
```cpp
UNavigationSystemV1* NavSys = UNavigationSystemV1::GetCurrent(GetWorld());
NavSys->Build(); // Rebuild entire NavMesh
```
### Dynamic Nav Mesh (Moving Obstacles)
```cpp
// Enable: Project Settings > Navigation System > Runtime Generation = Dynamic
// Mark actor as dynamic obstacle:
UStaticMeshComponent* Mesh = /* Get mesh */;
Mesh->SetCanEverAffectNavigation(true);
Mesh->bDynamicObstacle = true;
```
---
## Nav Links (Off-Mesh Connections)
### Nav Link Proxy (Jump, Teleport)
1. Place Actors > Navigation > Nav Link Proxy
2. Set up start and end points
3. Configure:
- **Direction**: One-way or bidirectional
- **Smart Link**: Animate character during traversal
---
## Crowd Management
### Detour Crowd (Avoid Overlapping)
```cpp
// Enable: Character Movement Component > Avoidance Enabled = true
// Configure avoidance group and flags
UCharacterMovementComponent* MoveComp = GetCharacterMovement();
MoveComp->SetAvoidanceGroup(1);
MoveComp->SetGroupsToAvoid(1);
MoveComp->SetAvoidanceEnabled(true);
```
---
## Performance Tips
### Nav Mesh Optimization
```cpp
// Reduce tile size for large worlds:
// Project Settings > Navigation System > Cell Size = 19 (default)
// Use Navigation Invokers for dynamic generation:
// Only generate NavMesh around players/important actors
```
---
## Debugging
### Visualize Nav Mesh
```cpp
// Console commands:
// show navigation - Toggle NavMesh visualization
// p - Toggle NavMesh (editor viewport)
// Draw debug path:
if (NavPath) {
for (int i = 0; i < NavPath->GetPathPoints().Num() - 1; i++) {
DrawDebugLine(GetWorld(), NavPath->GetPathPoints()[i], NavPath->GetPathPoints()[i + 1], FColor::Green, false, 5.0f, 0, 5.0f);
}
}
```
---
## Common Patterns
### Patrol Between Waypoints
```cpp
UPROPERTY(EditAnywhere, Category = "AI")
TArray<AActor*> PatrolPoints;
int32 CurrentPatrolIndex = 0;
void OnMoveCompleted(FAIRequestID RequestID, EPathFollowingResult::Type Result) {
if (Result == EPathFollowingResult::Success) {
// Move to next waypoint
CurrentPatrolIndex = (CurrentPatrolIndex + 1) % PatrolPoints.Num();
MoveToActor(PatrolPoints[CurrentPatrolIndex]);
}
}
```
### Chase Player
```cpp
void Tick(float DeltaTime) {
Super::Tick(DeltaTime);
AAIController* AIController = Cast<AAIController>(GetController());
APawn* PlayerPawn = GetWorld()->GetFirstPlayerController()->GetPawn();
if (AIController && PlayerPawn) {
float Distance = FVector::Dist(GetActorLocation(), PlayerPawn->GetActorLocation());
if (Distance < 1000.0f) {
// Chase player
AIController->MoveToActor(PlayerPawn, 100.0f);
} else {
// Stop chasing
AIController->StopMovement();
}
}
}
```
---
## Sources
- https://docs.unrealengine.com/5.7/en-US/navigation-system-in-unreal-engine/
- https://docs.unrealengine.com/5.7/en-US/ai-in-unreal-engine/

View File

@@ -0,0 +1,409 @@
# Unreal Engine 5.7 — Networking Module Reference
**Last verified:** 2026-02-13
**Knowledge Gap:** UE 5.7 networking improvements
---
## Overview
UE 5.7 networking:
- **Client-Server Architecture**: Server-authoritative (RECOMMENDED)
- **Replication**: Automatic state synchronization
- **RPCs (Remote Procedure Calls)**: Call functions across network
- **Relevancy**: Optimize bandwidth by only replicating relevant actors
---
## Basic Multiplayer Setup
### Enable Replication on Actor
```cpp
UCLASS()
class AMyActor : public AActor {
GENERATED_BODY()
public:
AMyActor() {
// ✅ Enable replication
bReplicates = true;
bAlwaysRelevant = true; // Always replicate to all clients
}
};
```
### Network Role Checks
```cpp
// Check role
if (HasAuthority()) {
// Running on server
}
if (GetLocalRole() == ROLE_AutonomousProxy) {
// This is the owning client (local player)
}
if (GetRemoteRole() == ROLE_SimulatedProxy) {
// This is a remote client (other players)
}
```
---
## Replicated Variables
### Basic Replication
```cpp
UPROPERTY(Replicated)
int32 Health;
UPROPERTY(Replicated)
FVector Position;
// ✅ Implement GetLifetimeReplicatedProps
void AMyActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const {
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyActor, Health);
DOREPLIFETIME(AMyActor, Position);
}
```
### Conditional Replication
```cpp
// Only replicate to owner
DOREPLIFETIME_CONDITION(AMyCharacter, Ammo, COND_OwnerOnly);
// Skip owner (replicate to everyone else)
DOREPLIFETIME_CONDITION(AMyCharacter, TeamID, COND_SkipOwner);
// Only when changed
DOREPLIFETIME_CONDITION(AMyCharacter, Score, COND_InitialOnly);
```
### RepNotify (Callback on Replication)
```cpp
UPROPERTY(ReplicatedUsing=OnRep_Health)
int32 Health;
UFUNCTION()
void OnRep_Health() {
// Called on clients when Health changes
UpdateHealthUI();
}
// Implement GetLifetimeReplicatedProps (same as above)
```
---
## RPCs (Remote Procedure Calls)
### Server RPC (Client → Server)
```cpp
// Client calls, server executes
UFUNCTION(Server, Reliable)
void Server_TakeDamage(int32 Damage);
void AMyCharacter::Server_TakeDamage_Implementation(int32 Damage) {
// Runs on server only
Health -= Damage;
if (Health <= 0) {
Server_Die();
}
}
bool AMyCharacter::Server_TakeDamage_Validate(int32 Damage) {
// Validate input (anti-cheat)
return Damage >= 0 && Damage <= 100;
}
```
### Client RPC (Server → Client)
```cpp
// Server calls, client executes
UFUNCTION(Client, Reliable)
void Client_ShowDeathScreen();
void AMyCharacter::Client_ShowDeathScreen_Implementation() {
// Runs on client only
ShowDeathUI();
}
```
### Multicast RPC (Server → All Clients)
```cpp
// Server calls, all clients execute
UFUNCTION(NetMulticast, Reliable)
void Multicast_PlayExplosion(FVector Location);
void AMyActor::Multicast_PlayExplosion_Implementation(FVector Location) {
// Runs on server and all clients
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ExplosionEffect, Location);
}
```
### RPC Reliability
```cpp
// Reliable: Guaranteed delivery (important events)
UFUNCTION(Server, Reliable)
void Server_FireWeapon();
// Unreliable: Best-effort delivery (frequent updates, position sync)
UFUNCTION(Server, Unreliable)
void Server_UpdateAim(FRotator AimRotation);
```
---
## Server-Authoritative Pattern (RECOMMENDED)
### Movement Example
```cpp
class AMyCharacter : public ACharacter {
UPROPERTY(Replicated)
FVector ServerPosition;
void Tick(float DeltaTime) override {
Super::Tick(DeltaTime);
if (GetLocalRole() == ROLE_AutonomousProxy) {
// Client: Send input to server
FVector Input = GetMovementInput();
Server_Move(Input);
// Client-side prediction (move locally)
AddMovementInput(Input);
}
if (HasAuthority()) {
// Server: Authoritative position
ServerPosition = GetActorLocation();
} else {
// Client: Interpolate toward server position
FVector NewPos = FMath::VInterpTo(GetActorLocation(), ServerPosition, DeltaTime, 5.0f);
SetActorLocation(NewPos);
}
}
UFUNCTION(Server, Unreliable)
void Server_Move(FVector Input);
void Server_Move_Implementation(FVector Input) {
// Server validates and applies movement
AddMovementInput(Input);
}
};
```
---
## Network Relevancy (Bandwidth Optimization)
### Custom Relevancy
```cpp
bool AMyActor::IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation) const {
// Only replicate if within range
float Distance = FVector::Dist(SrcLocation, GetActorLocation());
return Distance < 5000.0f;
}
```
### Always Relevant Actors
```cpp
AMyActor() {
bAlwaysRelevant = true; // Replicate to all clients (e.g., GameState, PlayerController)
bOnlyRelevantToOwner = true; // Only replicate to owner (e.g., PlayerController)
}
```
---
## Ownership
### Set Owner
```cpp
// Assign owner (important for RPCs and relevancy)
MyActor->SetOwner(OwningPlayerController);
```
### Check Owner
```cpp
if (GetOwner() == PlayerController) {
// This actor is owned by this player
}
```
---
## Game Mode & Game State
### Game Mode (Server Only)
```cpp
UCLASS()
class AMyGameMode : public AGameMode {
GENERATED_BODY()
public:
// Game mode only exists on server
// Use for server-side logic (spawning, scoring, rules)
};
```
### Game State (Replicated to All Clients)
```cpp
UCLASS()
class AMyGameState : public AGameState {
GENERATED_BODY()
public:
// ✅ Replicate game state to all clients
UPROPERTY(Replicated)
int32 RedTeamScore;
UPROPERTY(Replicated)
int32 BlueTeamScore;
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override {
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyGameState, RedTeamScore);
DOREPLIFETIME(AMyGameState, BlueTeamScore);
}
};
```
---
## Player Controller & Player State
### Player Controller (One per Player)
```cpp
UCLASS()
class AMyPlayerController : public APlayerController {
GENERATED_BODY()
public:
// Exists on server and owning client
// Use for player-specific logic, input handling
};
```
### Player State (Replicated Player Info)
```cpp
UCLASS()
class AMyPlayerState : public APlayerState {
GENERATED_BODY()
public:
UPROPERTY(Replicated)
int32 Kills;
UPROPERTY(Replicated)
int32 Deaths;
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override {
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyPlayerState, Kills);
DOREPLIFETIME(AMyPlayerState, Deaths);
}
};
```
---
## Sessions & Matchmaking
### Create Session
```cpp
#include "OnlineSubsystem.h"
#include "OnlineSessionSettings.h"
void CreateSession() {
IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();
TSharedPtr<FOnlineSessionSettings> SessionSettings = MakeShareable(new FOnlineSessionSettings());
SessionSettings->bIsLANMatch = false;
SessionSettings->NumPublicConnections = 4;
SessionSettings->bShouldAdvertise = true;
Sessions->CreateSession(0, FName("MySession"), *SessionSettings);
}
```
### Find Sessions
```cpp
void FindSessions() {
IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get();
IOnlineSessionPtr Sessions = OnlineSub->GetSessionInterface();
TSharedRef<FOnlineSessionSearch> SearchSettings = MakeShareable(new FOnlineSessionSearch());
SearchSettings->bIsLanQuery = false;
SearchSettings->MaxSearchResults = 20;
Sessions->FindSessions(0, SearchSettings);
}
```
---
## Performance Tips
### Reduce Bandwidth
```cpp
// Use unreliable RPCs for frequent updates
UFUNCTION(Server, Unreliable)
void Server_UpdatePosition(FVector Pos);
// Conditional replication (only replicate to relevant clients)
DOREPLIFETIME_CONDITION(AMyActor, Health, COND_OwnerOnly);
// Limit replication frequency
SetReplicationFrequency(10.0f); // Update 10 times per second (default 100)
```
---
## Debugging
### Network Debugging
```cpp
// Console commands:
// stat net - Show network stats
// stat netplayerupdate - Show player update stats
// NetEmulation PktLoss=10 - Simulate 10% packet loss
// NetEmulation PktLag=100 - Simulate 100ms latency
// Draw debug for replication:
UE_LOG(LogNet, Warning, TEXT("Replicating Health: %d"), Health);
```
---
## Sources
- https://docs.unrealengine.com/5.7/en-US/networking-and-multiplayer-in-unreal-engine/
- https://docs.unrealengine.com/5.7/en-US/actor-replication-in-unreal-engine/
- https://docs.unrealengine.com/5.7/en-US/rpcs-in-unreal-engine/

View File

@@ -0,0 +1,283 @@
# Unreal Engine 5.7 — Physics Module Reference
**Last verified:** 2026-02-13
**Knowledge Gap:** UE 5.7 Chaos Physics improvements
---
## Overview
UE 5 uses **Chaos Physics** (replaced PhysX in UE 4):
- Better performance
- Destruction support
- Vehicle physics improvements
---
## Rigid Body Physics
### Enable Physics on Static Mesh
```cpp
UStaticMeshComponent* MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
MeshComp->SetSimulatePhysics(true);
MeshComp->SetEnableGravity(true);
MeshComp->SetMassOverrideInKg(NAME_None, 50.0f); // 50 kg
```
### Apply Forces
```cpp
// Apply impulse (instant velocity change)
MeshComp->AddImpulse(FVector(0, 0, 1000), NAME_None, true);
// Apply force (continuous)
MeshComp->AddForce(FVector(0, 0, 500));
// Apply torque (rotation)
MeshComp->AddTorqueInRadians(FVector(0, 0, 100));
```
---
## Collision
### Collision Channels
```cpp
// Project Settings > Engine > Collision
// Define custom collision channels and responses
// Set collision in C++
MeshComp->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
MeshComp->SetCollisionObjectType(ECollisionChannel::ECC_Pawn);
MeshComp->SetCollisionResponseToAllChannels(ECR_Block);
MeshComp->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
```
### Collision Events
```cpp
// Enable collision events
MeshComp->SetNotifyRigidBodyCollision(true);
// Bind to OnComponentHit
MeshComp->OnComponentHit.AddDynamic(this, &AMyActor::OnHit);
UFUNCTION()
void AMyActor::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor,
UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) {
UE_LOG(LogTemp, Warning, TEXT("Hit %s"), *OtherActor->GetName());
}
```
### Overlap Events
```cpp
// Enable overlap events
MeshComp->SetGenerateOverlapEvents(true);
// Bind to OnComponentBeginOverlap
MeshComp->OnComponentBeginOverlap.AddDynamic(this, &AMyActor::OnOverlapBegin);
UFUNCTION()
void AMyActor::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) {
UE_LOG(LogTemp, Warning, TEXT("Overlapped %s"), *OtherActor->GetName());
}
```
---
## Raycasting (Line Traces)
### Single Line Trace
```cpp
FHitResult HitResult;
FVector Start = GetActorLocation();
FVector End = Start + GetActorForwardVector() * 1000.0f;
FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(this);
// Perform trace
bool bHit = GetWorld()->LineTraceSingleByChannel(
HitResult,
Start,
End,
ECC_Visibility,
QueryParams
);
if (bHit) {
UE_LOG(LogTemp, Warning, TEXT("Hit: %s"), *HitResult.GetActor()->GetName());
DrawDebugLine(GetWorld(), Start, HitResult.Location, FColor::Red, false, 2.0f);
}
```
### Multi Line Trace
```cpp
TArray<FHitResult> HitResults;
bool bHit = GetWorld()->LineTraceMultiByChannel(
HitResults,
Start,
End,
ECC_Visibility,
QueryParams
);
for (const FHitResult& Hit : HitResults) {
UE_LOG(LogTemp, Warning, TEXT("Hit: %s"), *Hit.GetActor()->GetName());
}
```
### Sweep (Thick Trace)
```cpp
FHitResult HitResult;
FCollisionShape Sphere = FCollisionShape::MakeSphere(50.0f);
bool bHit = GetWorld()->SweepSingleByChannel(
HitResult,
Start,
End,
FQuat::Identity,
ECC_Visibility,
Sphere,
QueryParams
);
```
---
## Character Movement
### Character Movement Component
```cpp
// Built into ACharacter class
UCharacterMovementComponent* MoveComp = GetCharacterMovement();
// Configure movement
MoveComp->MaxWalkSpeed = 600.0f;
MoveComp->JumpZVelocity = 600.0f;
MoveComp->AirControl = 0.2f;
MoveComp->GravityScale = 1.0f;
MoveComp->bOrientRotationToMovement = true;
```
### Add Movement Input
```cpp
// In Character class
void AMyCharacter::MoveForward(float Value) {
if (Value != 0.0f) {
AddMovementInput(GetActorForwardVector(), Value);
}
}
void AMyCharacter::MoveRight(float Value) {
if (Value != 0.0f) {
AddMovementInput(GetActorRightVector(), Value);
}
}
```
---
## Physical Materials
### Create Physical Material
1. Content Browser > Right Click > Physics > Physical Material
2. Configure properties:
- Friction: 0.0 - 1.0
- Restitution (bounciness): 0.0 - 1.0
### Assign Physical Material
```cpp
// In static mesh editor: Physics > Phys Material Override
// Or in C++:
MeshComp->SetPhysMaterialOverride(PhysicalMaterial);
```
---
## Constraints (Physics Joints)
### Physics Constraint Component
```cpp
UPhysicsConstraintComponent* Constraint = CreateDefaultSubobject<UPhysicsConstraintComponent>(TEXT("Constraint"));
Constraint->SetConstrainedComponents(ComponentA, NAME_None, ComponentB, NAME_None);
// Configure constraint
Constraint->SetLinearXLimit(ELinearConstraintMotion::LCM_Limited, 100.0f);
Constraint->SetLinearYLimit(ELinearConstraintMotion::LCM_Locked, 0.0f);
Constraint->SetLinearZLimit(ELinearConstraintMotion::LCM_Free, 0.0f);
Constraint->SetAngularSwing1Limit(EAngularConstraintMotion::ACM_Limited, 45.0f);
```
---
## Destruction (Chaos Destruction)
### Enable Chaos Destruction
```cpp
// Plugin: Enable "Chaos" plugin
// Create Geometry Collection asset for destructible objects
```
### Destroy Geometry Collection
```cpp
// Fracture mesh in Chaos editor
// In game, apply damage:
UGeometryCollectionComponent* GeoComp = /* Get component */;
GeoComp->ApplyPhysicsField(/* Field parameters */);
```
---
## Performance Tips
### Physics Optimization
```cpp
// Simplify collision shapes (use simple primitives)
MeshComp->SetCollisionEnabled(ECollisionEnabled::NoCollision); // Disable when not needed
// Use Physics Asset for skeletal meshes (simplified collision)
// Don't simulate physics for distant objects
// Reduce physics substeps:
// Project Settings > Engine > Physics > Max Substep Delta Time
```
---
## Debugging
### Physics Debug Visualization
```cpp
// Console commands:
// show collision - Show collision shapes
// p.Chaos.DebugDraw.Enabled 1 - Show Chaos debug
// pxvis collision - Visualize collision
// Draw debug shapes:
DrawDebugSphere(GetWorld(), Location, Radius, 12, FColor::Green, false, 2.0f);
DrawDebugBox(GetWorld(), Location, Extent, FColor::Red, false, 2.0f);
```
---
## Sources
- https://docs.unrealengine.com/5.7/en-US/physics-in-unreal-engine/
- https://docs.unrealengine.com/5.7/en-US/chaos-physics-overview-in-unreal-engine/

View File

@@ -0,0 +1,297 @@
# Unreal Engine 5.7 — Rendering Module Reference
**Last verified:** 2026-02-13
**Knowledge Gap:** UE 5.7 has Megalights, production-ready Substrate, and Lumen improvements
---
## Overview
UE 5.7 rendering stack:
- **Lumen**: Real-time global illumination (default)
- **Nanite**: Virtualized geometry for millions of triangles
- **Megalights**: Support for millions of dynamic lights (NEW in 5.5+)
- **Substrate**: Production-ready modular material system (NEW in 5.7)
---
## Lumen (Global Illumination)
### Enable Lumen
```cpp
// Project Settings > Engine > Rendering > Dynamic Global Illumination Method = Lumen
// Real-time GI, no lightmap baking needed
```
### Lumen Quality Settings
```ini
; DefaultEngine.ini
[/Script/Engine.RendererSettings]
r.Lumen.DiffuseColorBoost=1.0
r.Lumen.ScreenProbeGather.RadianceCache.NumFramesToKeepCached=2
```
### Lumen in C++
```cpp
// Check if Lumen is enabled
bool bIsLumenEnabled = IConsoleManager::Get().FindConsoleVariable(TEXT("r.DynamicGlobalIlluminationMethod"))->GetInt() == 1;
```
---
## Nanite (Virtualized Geometry)
### Enable Nanite on Static Mesh
1. Static Mesh Editor
2. Details > Nanite Settings > Enable Nanite Support
3. Save mesh (auto-builds Nanite data)
### Nanite in C++
```cpp
// Spawn Nanite mesh
UStaticMeshComponent* MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
MeshComp->SetStaticMesh(NaniteMesh); // Automatically uses Nanite if enabled
```
### Nanite Limitations
- No vertex animation (skeletal meshes)
- No world position offset (WPO) in materials
- Best for static, high-poly geometry
---
## Megalights (UE 5.5+)
### Enable Megalights
```cpp
// Project Settings > Engine > Rendering > Megalights = Enabled
// Supports millions of dynamic lights with minimal performance cost
```
### Megalights Usage
```cpp
// Add point lights as usual
UPointLightComponent* Light = CreateDefaultSubobject<UPointLightComponent>(TEXT("Light"));
Light->SetIntensity(5000.0f);
Light->SetAttenuationRadius(500.0f);
// Megalights automatically handles thousands/millions of these
```
---
## Substrate Materials (Production-Ready in 5.7)
### Enable Substrate
```cpp
// Project Settings > Engine > Substrate > Enable Substrate
// Restart editor
```
### Substrate Material Nodes
- **Substrate Slab**: Physical material layer (diffuse, specular, etc.)
- **Substrate Blend**: Blend multiple layers
- **Substrate Thin Film**: Iridescence, soap bubbles
- **Substrate Hair**: Hair-specific shading
### Example Substrate Material Graph
```
Substrate Slab (Diffuse)
└─ Base Color: Texture Sample
└─ Roughness: Constant (0.5)
└─ Metallic: Constant (0.0)
└─ Connect to Material Output
```
---
## Materials (C++ API)
### Dynamic Material Instances
```cpp
// Create dynamic material instance
UMaterialInstanceDynamic* DynMat = UMaterialInstanceDynamic::Create(BaseMaterial, this);
// Set parameters
DynMat->SetVectorParameterValue(TEXT("BaseColor"), FLinearColor::Red);
DynMat->SetScalarParameterValue(TEXT("Metallic"), 0.8f);
DynMat->SetTextureParameterValue(TEXT("DiffuseTexture"), MyTexture);
// Apply to mesh
MeshComp->SetMaterial(0, DynMat);
```
---
## Post-Processing
### Post-Process Volume
```cpp
// Add to level
APostProcessVolume* PPV = GetWorld()->SpawnActor<APostProcessVolume>();
PPV->bUnbound = true; // Affect entire world
// Configure settings
PPV->Settings.bOverride_MotionBlurAmount = true;
PPV->Settings.MotionBlurAmount = 0.5f;
PPV->Settings.bOverride_BloomIntensity = true;
PPV->Settings.BloomIntensity = 1.0f;
```
### Post-Process in C++
```cpp
// Access camera post-process settings
APlayerController* PC = GetWorld()->GetFirstPlayerController();
if (APlayerCameraManager* CamManager = PC->PlayerCameraManager) {
CamManager->PostProcessBlendWeight = 1.0f;
CamManager->PostProcessSettings.BloomIntensity = 2.0f;
}
```
---
## Lighting
### Directional Light (Sun)
```cpp
ADirectionalLight* Sun = GetWorld()->SpawnActor<ADirectionalLight>();
Sun->SetActorRotation(FRotator(-45.f, 0.f, 0.f));
Sun->GetLightComponent()->SetIntensity(10.0f);
Sun->GetLightComponent()->bCastShadows = true;
```
### Point Light
```cpp
APointLight* Light = GetWorld()->SpawnActor<APointLight>();
Light->SetActorLocation(FVector(0, 0, 200));
Light->GetPointLightComponent()->SetIntensity(5000.0f);
Light->GetPointLightComponent()->SetAttenuationRadius(1000.0f);
Light->GetPointLightComponent()->SetLightColor(FLinearColor::Red);
```
### Spot Light
```cpp
ASpotLight* Spotlight = GetWorld()->SpawnActor<ASpotLight>();
Spotlight->GetSpotLightComponent()->SetInnerConeAngle(20.0f);
Spotlight->GetSpotLightComponent()->SetOuterConeAngle(40.0f);
```
---
## Render Targets (Render to Texture)
### Create Render Target
```cpp
// Create render target asset (2D texture)
UTextureRenderTarget2D* RenderTarget = NewObject<UTextureRenderTarget2D>();
RenderTarget->InitAutoFormat(512, 512); // 512x512 resolution
RenderTarget->UpdateResourceImmediate();
// Render scene to texture
UKismetRenderingLibrary::DrawMaterialToRenderTarget(
GetWorld(),
RenderTarget,
MaterialToDraw
);
```
---
## Custom Render Passes (Advanced)
### Render Dependency Graph (RDG)
```cpp
// UE5 uses Render Dependency Graph for custom rendering
// Example: Custom post-process pass
#include "RenderGraphBuilder.h"
void RenderCustomPass(FRDGBuilder& GraphBuilder, const FViewInfo& View) {
FRDGTextureRef SceneColor = /* Get scene color texture */;
// Define pass parameters
struct FPassParameters {
FRDGTextureRef InputTexture;
};
FPassParameters* PassParams = GraphBuilder.AllocParameters<FPassParameters>();
PassParams->InputTexture = SceneColor;
// Add render pass
GraphBuilder.AddPass(
RDG_EVENT_NAME("CustomPass"),
PassParams,
ERDGPassFlags::Raster,
[](FRHICommandList& RHICmdList, const FPassParameters* Params) {
// Render commands
}
);
}
```
---
## Performance
### Render Stats
```cpp
// Console commands for profiling:
// stat fps - Show FPS
// stat unit - Show frame time breakdown
// stat gpu - Show GPU timings
// profilegpu - Detailed GPU profile
```
### Scalability Settings
```cpp
// Get current scalability settings
UGameUserSettings* Settings = UGameUserSettings::GetGameUserSettings();
int32 ViewDistanceQuality = Settings->GetViewDistanceQuality(); // 0-4
// Set scalability
Settings->SetViewDistanceQuality(3); // High
Settings->SetShadowQuality(2); // Medium
Settings->ApplySettings(false);
```
---
## Debugging
### Visualize Render Features
```
Console commands:
- r.Lumen.Visualize 1 - Show Lumen debug
- r.Nanite.Visualize 1 - Show Nanite triangles
- viewmode wireframe - Wireframe mode
- viewmode unlit - Disable lighting
- show collision - Show collision meshes
```
---
## Sources
- https://docs.unrealengine.com/5.7/en-US/lumen-global-illumination-and-reflections-in-unreal-engine/
- https://docs.unrealengine.com/5.7/en-US/nanite-virtualized-geometry-in-unreal-engine/
- https://docs.unrealengine.com/5.7/en-US/substrate-materials-in-unreal-engine/

View File

@@ -0,0 +1,353 @@
# Unreal Engine 5.7 — UI Module Reference
**Last verified:** 2026-02-13
**Knowledge Gap:** UE 5.7 UMG and CommonUI improvements
---
## Overview
UE 5.7 UI systems:
- **UMG (Unreal Motion Graphics)**: Visual widget-based UI (RECOMMENDED)
- **CommonUI**: Cross-platform input-aware UI framework (console/PC)
- **Slate**: Low-level C++ UI (engine/editor UI)
---
## UMG (Unreal Motion Graphics)
### Create Widget Blueprint
1. Content Browser > User Interface > Widget Blueprint
2. Open Widget Designer
3. Drag widgets from Palette: Button, Text, Image, ProgressBar, etc.
---
## Basic UMG Setup in C++
### Create and Display Widget
```cpp
#include "Blueprint/UserWidget.h"
UPROPERTY(EditAnywhere, Category = "UI")
TSubclassOf<UUserWidget> HealthBarWidgetClass;
void AMyCharacter::BeginPlay() {
Super::BeginPlay();
// Create widget
UUserWidget* HealthBarWidget = CreateWidget<UUserWidget>(GetWorld(), HealthBarWidgetClass);
// Add to viewport
HealthBarWidget->AddToViewport();
}
```
### Remove Widget
```cpp
HealthBarWidget->RemoveFromParent();
```
---
## Access Widget Elements from C++
### Bind to Widget Elements
```cpp
UCLASS()
class UMyHealthWidget : public UUserWidget {
GENERATED_BODY()
public:
// ✅ Bind to widget elements (must match names in Widget Blueprint)
UPROPERTY(meta = (BindWidget))
TObjectPtr<UTextBlock> HealthText;
UPROPERTY(meta = (BindWidget))
TObjectPtr<UProgressBar> HealthBar;
void UpdateHealth(int32 CurrentHealth, int32 MaxHealth) {
HealthText->SetText(FText::FromString(FString::Printf(TEXT("%d / %d"), CurrentHealth, MaxHealth)));
HealthBar->SetPercent((float)CurrentHealth / MaxHealth);
}
};
```
---
## Common UMG Widgets
### Text Block
```cpp
UPROPERTY(meta = (BindWidget))
TObjectPtr<UTextBlock> ScoreText;
ScoreText->SetText(FText::FromString(TEXT("Score: 100")));
ScoreText->SetColorAndOpacity(FLinearColor::Green);
```
### Button
```cpp
UPROPERTY(meta = (BindWidget))
TObjectPtr<UButton> PlayButton;
void NativeConstruct() override {
Super::NativeConstruct();
// Bind button click
PlayButton->OnClicked.AddDynamic(this, &UMyMenuWidget::OnPlayClicked);
}
UFUNCTION()
void OnPlayClicked() {
UE_LOG(LogTemp, Warning, TEXT("Play clicked"));
}
```
### Image
```cpp
UPROPERTY(meta = (BindWidget))
TObjectPtr<UImage> PlayerAvatar;
PlayerAvatar->SetBrushFromTexture(AvatarTexture);
PlayerAvatar->SetColorAndOpacity(FLinearColor::White);
```
### Progress Bar
```cpp
UPROPERTY(meta = (BindWidget))
TObjectPtr<UProgressBar> HealthBar;
HealthBar->SetPercent(0.75f); // 75%
HealthBar->SetFillColorAndOpacity(FLinearColor::Red);
```
### Slider
```cpp
UPROPERTY(meta = (BindWidget))
TObjectPtr<USlider> VolumeSlider;
void NativeConstruct() override {
Super::NativeConstruct();
VolumeSlider->OnValueChanged.AddDynamic(this, &UMyWidget::OnVolumeChanged);
}
UFUNCTION()
void OnVolumeChanged(float Value) {
// Value is 0.0 - 1.0
UE_LOG(LogTemp, Warning, TEXT("Volume: %f"), Value);
}
```
### EditableTextBox (Input Field)
```cpp
UPROPERTY(meta = (BindWidget))
TObjectPtr<UEditableTextBox> PlayerNameInput;
void NativeConstruct() override {
Super::NativeConstruct();
PlayerNameInput->OnTextChanged.AddDynamic(this, &UMyWidget::OnNameChanged);
}
UFUNCTION()
void OnNameChanged(const FText& Text) {
FString PlayerName = Text.ToString();
}
```
---
## UMG Animations
### Play Animation
```cpp
UPROPERTY(Transient, meta = (BindWidgetAnim))
TObjectPtr<UWidgetAnimation> FadeInAnimation;
void ShowUI() {
PlayAnimation(FadeInAnimation);
}
```
### Stop Animation
```cpp
StopAnimation(FadeInAnimation);
```
---
## Canvas Panel (Layout)
### Canvas Panel (Absolute Positioning)
```cpp
// Use in Widget Blueprint for absolute positioning
// Anchor widgets to corners/edges for responsive UI
```
### Vertical Box (Stack Vertically)
```cpp
// Auto-stacks children vertically
```
### Horizontal Box (Stack Horizontally)
```cpp
// Auto-stacks children horizontally
```
### Grid Panel (Grid Layout)
```cpp
// Arranges children in a grid
```
---
## World Space UI (3D UI)
### Widget Component (3D UI in World)
```cpp
#include "Components/WidgetComponent.h"
UWidgetComponent* HealthBarWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("HealthBar"));
HealthBarWidget->SetupAttachment(RootComponent);
HealthBarWidget->SetWidgetClass(HealthBarWidgetClass);
HealthBarWidget->SetWidgetSpace(EWidgetSpace::World); // 3D world space
HealthBarWidget->SetDrawSize(FVector2D(200, 50));
```
---
## Input Handling in UMG
### Override Keyboard Input
```cpp
UCLASS()
class UMyWidget : public UUserWidget {
GENERATED_BODY()
public:
virtual FReply NativeOnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) override {
if (InKeyEvent.GetKey() == EKeys::Escape) {
// Handle Escape key
CloseMenu();
return FReply::Handled();
}
return Super::NativeOnKeyDown(InGeometry, InKeyEvent);
}
};
```
---
## CommonUI (Cross-Platform Input)
### Enable CommonUI Plugin
```cpp
// Enable: Edit > Plugins > CommonUI
// Restart editor
```
### Use CommonUI Widgets
```cpp
// CommonUI widgets:
// - CommonActivatableWidget: Base for screens/menus
// - CommonButtonBase: Input-aware button (gamepad + mouse)
// - CommonTextBlock: Text with styling
```
### CommonActivatableWidget Example
```cpp
UCLASS()
class UMyMenuWidget : public UCommonActivatableWidget {
GENERATED_BODY()
public:
virtual void NativeOnActivated() override {
Super::NativeOnActivated();
// Menu activated (shown)
}
virtual void NativeOnDeactivated() override {
Super::NativeOnDeactivated();
// Menu deactivated (hidden)
}
};
```
---
## HUD Class (Alternative to UMG)
### Create HUD
```cpp
UCLASS()
class AMyHUD : public AHUD {
GENERATED_BODY()
public:
virtual void DrawHUD() override {
Super::DrawHUD();
// Draw text
DrawText(TEXT("Score: 100"), FLinearColor::White, 50, 50);
// Draw texture
DrawTexture(CrosshairTexture, Canvas->SizeX / 2, Canvas->SizeY / 2, 32, 32);
}
};
```
---
## Performance Tips
### Optimize UMG
```cpp
// Invalidation boxes: Only redraw when content changes
// Add "Invalidation Box" widget to Widget Blueprint
// Disable tick if not needed
bIsFocusable = false;
SetVisibility(ESlateVisibility::Collapsed); // Collapsed = not rendered
```
---
## Debugging
### UI Debug Commands
```cpp
// Console commands:
// widget.debug - Show widget hierarchy
// Slate.ShowDebugOutlines 1 - Show widget bounds
// stat slate - Show Slate performance
```
---
## Sources
- https://docs.unrealengine.com/5.7/en-US/umg-ui-designer-for-unreal-engine/
- https://docs.unrealengine.com/5.7/en-US/commonui-plugin-for-advanced-user-interfaces-in-unreal-engine/