添加 claude code game studios 到项目
This commit is contained in:
389
docs/engine-reference/unreal/plugins/common-ui.md
Normal file
389
docs/engine-reference/unreal/plugins/common-ui.md
Normal file
@@ -0,0 +1,389 @@
|
||||
# Unreal Engine 5.7 — CommonUI Plugin
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Status:** Production-Ready
|
||||
**Plugin:** `CommonUI` (built-in, enable in Plugins)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**CommonUI** is a cross-platform UI framework that automatically handles input routing
|
||||
for gamepad, mouse, and touch. It's designed for games that need to work seamlessly
|
||||
across PC, console, and mobile platforms with minimal platform-specific code.
|
||||
|
||||
**Use CommonUI for:**
|
||||
- Multi-platform games (console + PC)
|
||||
- Automatic gamepad/mouse/touch input routing
|
||||
- Input-agnostic UI (same UI works with any input method)
|
||||
- Widget focus and navigation
|
||||
- Action bars and input hints
|
||||
|
||||
**DON'T use CommonUI for:**
|
||||
- PC-only games with mouse-only UI (standard UMG is simpler)
|
||||
- Simple UI with no navigation requirements
|
||||
|
||||
---
|
||||
|
||||
## Key Differences from Standard UMG
|
||||
|
||||
| Feature | Standard UMG | CommonUI |
|
||||
|---------|--------------|----------|
|
||||
| **Input Handling** | Manual per widget | Automatic routing |
|
||||
| **Focus Management** | Basic | Advanced navigation |
|
||||
| **Platform Switching** | Manual detection | Automatic |
|
||||
| **Input Prompts** | Hardcode icons | Dynamic per platform |
|
||||
| **Screen Stack** | Manual | Built-in activatable widgets |
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Enable Plugin
|
||||
|
||||
`Edit > Plugins > CommonUI > Enabled > Restart`
|
||||
|
||||
### 2. Configure Project Settings
|
||||
|
||||
`Project Settings > Plugins > CommonUI`:
|
||||
- **Default Input Type**: Gamepad (or auto-detect)
|
||||
- **Platform-Specific Settings**: Configure input icons per platform
|
||||
|
||||
### 3. Create Common Input Settings Asset
|
||||
|
||||
1. Content Browser > Input > Common Input Settings
|
||||
2. Configure input data per platform:
|
||||
- Default Gamepad Data
|
||||
- Default Mouse & Keyboard Data
|
||||
- Default Touch Data
|
||||
|
||||
---
|
||||
|
||||
## Core Widgets
|
||||
|
||||
### CommonActivatableWidget (Screen Management)
|
||||
|
||||
Base class for screens/menus that can be activated/deactivated.
|
||||
|
||||
```cpp
|
||||
#include "CommonActivatableWidget.h"
|
||||
|
||||
UCLASS()
|
||||
class UMyMenuWidget : public UCommonActivatableWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
virtual void NativeOnActivated() override {
|
||||
Super::NativeOnActivated();
|
||||
// Menu is now visible and focused
|
||||
UE_LOG(LogTemp, Warning, TEXT("Menu activated"));
|
||||
}
|
||||
|
||||
virtual void NativeOnDeactivated() override {
|
||||
Super::NativeOnDeactivated();
|
||||
// Menu is now hidden
|
||||
UE_LOG(LogTemp, Warning, TEXT("Menu deactivated"));
|
||||
}
|
||||
|
||||
virtual UWidget* NativeGetDesiredFocusTarget() const override {
|
||||
// Return widget that should receive focus (e.g., first button)
|
||||
return PlayButton;
|
||||
}
|
||||
|
||||
private:
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonButtonBase> PlayButton;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### CommonButtonBase (Input-Aware Button)
|
||||
|
||||
Replaces standard UMG Button. Automatically handles gamepad/mouse/keyboard input.
|
||||
|
||||
```cpp
|
||||
#include "CommonButtonBase.h"
|
||||
|
||||
UCLASS()
|
||||
class UMyMenuWidget : public UCommonActivatableWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonButtonBase> PlayButton;
|
||||
|
||||
virtual void NativeConstruct() override {
|
||||
Super::NativeConstruct();
|
||||
|
||||
// Bind button click (works with any input method)
|
||||
PlayButton->OnClicked().AddUObject(this, &UMyMenuWidget::OnPlayClicked);
|
||||
|
||||
// Set button text
|
||||
PlayButton->SetButtonText(FText::FromString(TEXT("Play")));
|
||||
}
|
||||
|
||||
void OnPlayClicked() {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Play clicked"));
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### CommonTextBlock (Styled Text)
|
||||
|
||||
Text widget with CommonUI styling support.
|
||||
|
||||
```cpp
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonTextBlock> TitleText;
|
||||
|
||||
TitleText->SetText(FText::FromString(TEXT("Main Menu")));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### CommonActionWidget (Input Prompts)
|
||||
|
||||
Displays input prompts (e.g., "Press A to Continue", automatically shows correct button icon).
|
||||
|
||||
```cpp
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonActionWidget> ConfirmActionWidget;
|
||||
|
||||
// Bind to input action
|
||||
ConfirmActionWidget->SetInputAction(ConfirmInputActionData);
|
||||
// Automatically shows correct icon (A on Xbox, X on PlayStation, Enter on PC)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Widget Stack (Screen Management)
|
||||
|
||||
### CommonActivatableWidgetStack
|
||||
|
||||
Manages a stack of screens (e.g., Main Menu → Settings → Controls).
|
||||
|
||||
```cpp
|
||||
#include "Widgets/CommonActivatableWidgetContainer.h"
|
||||
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonActivatableWidgetStack> WidgetStack;
|
||||
|
||||
// Push new screen onto stack
|
||||
void ShowSettingsMenu() {
|
||||
WidgetStack->AddWidget(USettingsMenuWidget::StaticClass());
|
||||
}
|
||||
|
||||
// Pop current screen (go back)
|
||||
void GoBack() {
|
||||
WidgetStack->DeactivateWidget();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input Actions (CommonUI Style)
|
||||
|
||||
### Define Input Actions
|
||||
|
||||
Create **Common Input Action Data Table**:
|
||||
1. Content Browser > Miscellaneous > Data Table
|
||||
2. Row Structure: `CommonInputActionDataBase`
|
||||
3. Add rows for actions (Confirm, Cancel, Navigate, etc.)
|
||||
|
||||
Example row:
|
||||
- **Action Name**: Confirm
|
||||
- **Default Input**: Gamepad Face Button Bottom (A/Cross)
|
||||
- **Alternate Inputs**: Enter (keyboard), Left Mouse Button
|
||||
|
||||
---
|
||||
|
||||
### Bind Input Actions in Widget
|
||||
|
||||
```cpp
|
||||
#include "Input/CommonUIActionRouterBase.h"
|
||||
|
||||
UCLASS()
|
||||
class UMyWidget : public UCommonActivatableWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
virtual void NativeOnActivated() override {
|
||||
Super::NativeOnActivated();
|
||||
|
||||
// Bind input action
|
||||
FBindUIActionArgs BindArgs(ConfirmInputAction, FSimpleDelegate::CreateUObject(this, &UMyWidget::OnConfirm));
|
||||
BindArgs.bDisplayInActionBar = true; // Show in action bar
|
||||
RegisterUIActionBinding(BindArgs);
|
||||
}
|
||||
|
||||
void OnConfirm() {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Confirmed"));
|
||||
}
|
||||
|
||||
private:
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||
FDataTableRowHandle ConfirmInputAction;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Focus & Navigation
|
||||
|
||||
### Automatic Gamepad Navigation
|
||||
|
||||
CommonUI automatically handles gamepad navigation (D-Pad/Stick to move between buttons).
|
||||
|
||||
```cpp
|
||||
// In Widget Blueprint:
|
||||
// - Widgets are automatically navigable if they inherit from CommonButton/CommonUserWidget
|
||||
// - Focus order is determined by widget hierarchy and layout
|
||||
```
|
||||
|
||||
### Custom Focus Navigation
|
||||
|
||||
```cpp
|
||||
// Override focus navigation
|
||||
virtual UWidget* NativeGetDesiredFocusTarget() const override {
|
||||
return FirstButton; // Return widget that should receive focus
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input Mode (Game vs UI)
|
||||
|
||||
### Switch Input Mode
|
||||
|
||||
```cpp
|
||||
#include "CommonUIExtensions.h"
|
||||
|
||||
// Switch to UI-only mode (pause game, show cursor)
|
||||
UCommonUIExtensions::PushStreamedGameplayUIInputConfig(this, FrontendInputConfig);
|
||||
|
||||
// Return to game mode (hide cursor, resume gameplay)
|
||||
UCommonUIExtensions::PopInputConfig(this);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Platform-Specific Input Icons
|
||||
|
||||
### Configure Input Icons
|
||||
|
||||
1. Create **Common Input Base Controller Data** asset for each platform:
|
||||
- Gamepad (Xbox, PlayStation, Switch)
|
||||
- Mouse & Keyboard
|
||||
- Touch
|
||||
|
||||
2. Assign platform-specific icons:
|
||||
- Gamepad Face Button Bottom: `A` (Xbox), `Cross` (PlayStation)
|
||||
- Confirm Key: `Enter` icon
|
||||
|
||||
3. Assign to **Common Input Settings** asset
|
||||
|
||||
### Automatically Display Correct Icons
|
||||
|
||||
```cpp
|
||||
// CommonActionWidget automatically shows correct icon for current platform
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonActionWidget> JumpActionWidget;
|
||||
|
||||
JumpActionWidget->SetInputAction(JumpInputActionData);
|
||||
// Shows "A" on Xbox, "Cross" on PlayStation, "Space" on PC
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Main Menu with Navigation
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class UMainMenuWidget : public UCommonActivatableWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonButtonBase> PlayButton;
|
||||
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonButtonBase> SettingsButton;
|
||||
|
||||
UPROPERTY(meta = (BindWidget))
|
||||
TObjectPtr<UCommonButtonBase> QuitButton;
|
||||
|
||||
virtual void NativeConstruct() override {
|
||||
Super::NativeConstruct();
|
||||
|
||||
PlayButton->OnClicked().AddUObject(this, &UMainMenuWidget::OnPlayClicked);
|
||||
SettingsButton->OnClicked().AddUObject(this, &UMainMenuWidget::OnSettingsClicked);
|
||||
QuitButton->OnClicked().AddUObject(this, &UMainMenuWidget::OnQuitClicked);
|
||||
}
|
||||
|
||||
virtual UWidget* NativeGetDesiredFocusTarget() const override {
|
||||
return PlayButton; // Focus "Play" button when menu opens
|
||||
}
|
||||
|
||||
void OnPlayClicked() { /* Start game */ }
|
||||
void OnSettingsClicked() { /* Open settings */ }
|
||||
void OnQuitClicked() { /* Quit game */ }
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Pause Menu with Back Action
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class UPauseMenuWidget : public UCommonActivatableWidget {
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Input")
|
||||
FDataTableRowHandle BackInputAction; // Assign "Cancel" action in Blueprint
|
||||
|
||||
virtual void NativeOnActivated() override {
|
||||
Super::NativeOnActivated();
|
||||
|
||||
// Bind "Back" input (B/Circle/Escape)
|
||||
FBindUIActionArgs BindArgs(BackInputAction, FSimpleDelegate::CreateUObject(this, &UPauseMenuWidget::OnBack));
|
||||
RegisterUIActionBinding(BindArgs);
|
||||
}
|
||||
|
||||
void OnBack() {
|
||||
DeactivateWidget(); // Close pause menu
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
- Use **CommonActivatableWidgetStack** for screen management (automatically handles activation/deactivation)
|
||||
- Avoid creating/destroying widgets every frame (reuse widgets)
|
||||
- Use **Lazy Widgets** for complex menus (only create when needed)
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### CommonUI Debug Commands
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// CommonUI.DumpActivatableTree - Show active widget hierarchy
|
||||
// CommonUI.DumpActionBindings - Show registered input actions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/commonui-plugin-for-advanced-user-interfaces-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/commonui-quickstart-guide-for-unreal-engine/
|
||||
386
docs/engine-reference/unreal/plugins/gameplay-ability-system.md
Normal file
386
docs/engine-reference/unreal/plugins/gameplay-ability-system.md
Normal file
@@ -0,0 +1,386 @@
|
||||
# Unreal Engine 5.7 — Gameplay Ability System (GAS)
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Status:** Production-Ready
|
||||
**Plugin:** `GameplayAbilities` (built-in, enable in Plugins)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Gameplay Ability System (GAS)** is a modular framework for building abilities, attributes,
|
||||
effects, and gameplay mechanics. It's the standard for RPGs, MOBAs, shooters with abilities,
|
||||
and any game with complex ability systems.
|
||||
|
||||
**Use GAS for:**
|
||||
- Character abilities (spells, skills, attacks)
|
||||
- Attributes (health, mana, stamina, stats)
|
||||
- Buffs/debuffs (temporary effects)
|
||||
- Cooldowns and costs
|
||||
- Damage calculation
|
||||
- Multiplayer-ready ability replication
|
||||
|
||||
---
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### 1. **Ability System Component** (ASC)
|
||||
- The main component that owns abilities, attributes, and effects
|
||||
- Added to Characters or PlayerStates
|
||||
|
||||
### 2. **Gameplay Abilities**
|
||||
- Individual skills/actions (fireball, heal, dash, etc.)
|
||||
- Activated, committed (cost/cooldown), and can be cancelled
|
||||
|
||||
### 3. **Attributes & Attribute Sets**
|
||||
- Stats that can be modified (Health, Mana, Stamina, Strength, etc.)
|
||||
- Stored in Attribute Sets
|
||||
|
||||
### 4. **Gameplay Effects**
|
||||
- Modify attributes (damage, healing, buffs, debuffs)
|
||||
- Can be instant, duration-based, or infinite
|
||||
|
||||
### 5. **Gameplay Tags**
|
||||
- Hierarchical tags for ability logic (e.g., `Ability.Attack.Melee`, `Status.Stunned`)
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Enable Plugin
|
||||
|
||||
`Edit > Plugins > Gameplay Abilities > Enabled > Restart`
|
||||
|
||||
### 2. Add Ability System Component
|
||||
|
||||
```cpp
|
||||
#include "AbilitySystemComponent.h"
|
||||
#include "AttributeSet.h"
|
||||
|
||||
UCLASS()
|
||||
class AMyCharacter : public ACharacter {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AMyCharacter() {
|
||||
// Create ASC
|
||||
AbilitySystemComponent = CreateDefaultSubobject<UAbilitySystemComponent>(TEXT("AbilitySystem"));
|
||||
AbilitySystemComponent->SetIsReplicated(true);
|
||||
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);
|
||||
|
||||
// Create Attribute Set
|
||||
AttributeSet = CreateDefaultSubobject<UMyAttributeSet>(TEXT("AttributeSet"));
|
||||
}
|
||||
|
||||
protected:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Abilities")
|
||||
TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
|
||||
|
||||
UPROPERTY()
|
||||
TObjectPtr<const UAttributeSet> AttributeSet;
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Initialize ASC (Important for Multiplayer)
|
||||
|
||||
```cpp
|
||||
void AMyCharacter::PossessedBy(AController* NewController) {
|
||||
Super::PossessedBy(NewController);
|
||||
|
||||
// Server: Initialize ASC
|
||||
if (AbilitySystemComponent) {
|
||||
AbilitySystemComponent->InitAbilityActorInfo(this, this);
|
||||
GiveDefaultAbilities();
|
||||
}
|
||||
}
|
||||
|
||||
void AMyCharacter::OnRep_PlayerState() {
|
||||
Super::OnRep_PlayerState();
|
||||
|
||||
// Client: Initialize ASC
|
||||
if (AbilitySystemComponent) {
|
||||
AbilitySystemComponent->InitAbilityActorInfo(this, this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Attributes & Attribute Sets
|
||||
|
||||
### Create Attribute Set
|
||||
|
||||
```cpp
|
||||
#include "AttributeSet.h"
|
||||
#include "AbilitySystemComponent.h"
|
||||
|
||||
UCLASS()
|
||||
class UMyAttributeSet : public UAttributeSet {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UMyAttributeSet();
|
||||
|
||||
// Health
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Attributes", ReplicatedUsing = OnRep_Health)
|
||||
FGameplayAttributeData Health;
|
||||
ATTRIBUTE_ACCESSORS(UMyAttributeSet, Health)
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Attributes", ReplicatedUsing = OnRep_MaxHealth)
|
||||
FGameplayAttributeData MaxHealth;
|
||||
ATTRIBUTE_ACCESSORS(UMyAttributeSet, MaxHealth)
|
||||
|
||||
// Mana
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Attributes", ReplicatedUsing = OnRep_Mana)
|
||||
FGameplayAttributeData Mana;
|
||||
ATTRIBUTE_ACCESSORS(UMyAttributeSet, Mana)
|
||||
|
||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
|
||||
protected:
|
||||
UFUNCTION()
|
||||
virtual void OnRep_Health(const FGameplayAttributeData& OldHealth);
|
||||
|
||||
UFUNCTION()
|
||||
virtual void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);
|
||||
|
||||
UFUNCTION()
|
||||
virtual void OnRep_Mana(const FGameplayAttributeData& OldMana);
|
||||
};
|
||||
```
|
||||
|
||||
### Implement Attribute Set
|
||||
|
||||
```cpp
|
||||
#include "Net/UnrealNetwork.h"
|
||||
|
||||
UMyAttributeSet::UMyAttributeSet() {
|
||||
// Default values
|
||||
Health = 100.0f;
|
||||
MaxHealth = 100.0f;
|
||||
Mana = 50.0f;
|
||||
}
|
||||
|
||||
void UMyAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const {
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
|
||||
DOREPLIFETIME_CONDITION_NOTIFY(UMyAttributeSet, Health, COND_None, REPNOTIFY_Always);
|
||||
DOREPLIFETIME_CONDITION_NOTIFY(UMyAttributeSet, MaxHealth, COND_None, REPNOTIFY_Always);
|
||||
DOREPLIFETIME_CONDITION_NOTIFY(UMyAttributeSet, Mana, COND_None, REPNOTIFY_Always);
|
||||
}
|
||||
|
||||
void UMyAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth) {
|
||||
GAMEPLAYATTRIBUTE_REPNOTIFY(UMyAttributeSet, Health, OldHealth);
|
||||
}
|
||||
|
||||
// Implement other OnRep functions similarly...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gameplay Abilities
|
||||
|
||||
### Create Gameplay Ability
|
||||
|
||||
```cpp
|
||||
#include "Abilities/GameplayAbility.h"
|
||||
|
||||
UCLASS()
|
||||
class UGA_Fireball : public UGameplayAbility {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGA_Fireball() {
|
||||
// Ability config
|
||||
InstancingPolicy = EGameplayAbilityInstancingPolicy::InstancedPerActor;
|
||||
NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::ServerInitiated;
|
||||
|
||||
// Tags
|
||||
AbilityTags.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack.Fireball")));
|
||||
}
|
||||
|
||||
virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo,
|
||||
const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override {
|
||||
|
||||
if (!CommitAbility(Handle, ActorInfo, ActivationInfo)) {
|
||||
// Failed to commit (not enough mana, on cooldown, etc.)
|
||||
EndAbility(Handle, ActorInfo, ActivationInfo, true, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Spawn fireball projectile
|
||||
SpawnFireball();
|
||||
|
||||
// End ability
|
||||
EndAbility(Handle, ActorInfo, ActivationInfo, true, false);
|
||||
}
|
||||
|
||||
void SpawnFireball() {
|
||||
// Spawn fireball logic
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Grant Abilities to Character
|
||||
|
||||
```cpp
|
||||
void AMyCharacter::GiveDefaultAbilities() {
|
||||
if (!HasAuthority() || !AbilitySystemComponent) return;
|
||||
|
||||
// Grant abilities
|
||||
AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(UGA_Fireball::StaticClass(), 1, INDEX_NONE, this));
|
||||
AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(UGA_Heal::StaticClass(), 1, INDEX_NONE, this));
|
||||
}
|
||||
```
|
||||
|
||||
### Activate Ability
|
||||
|
||||
```cpp
|
||||
// Activate by class
|
||||
AbilitySystemComponent->TryActivateAbilityByClass(UGA_Fireball::StaticClass());
|
||||
|
||||
// Activate by tag
|
||||
FGameplayTagContainer TagContainer;
|
||||
TagContainer.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack.Fireball")));
|
||||
AbilitySystemComponent->TryActivateAbilitiesByTag(TagContainer);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gameplay Effects
|
||||
|
||||
### Create Gameplay Effect (Damage)
|
||||
|
||||
```cpp
|
||||
// Create Blueprint: Content Browser > Gameplay > Gameplay Effect
|
||||
|
||||
// OR in C++:
|
||||
UCLASS()
|
||||
class UGE_Damage : public UGameplayEffect {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGE_Damage() {
|
||||
// Instant damage
|
||||
DurationPolicy = EGameplayEffectDurationType::Instant;
|
||||
|
||||
// Modifier: Reduce Health
|
||||
FGameplayModifierInfo ModifierInfo;
|
||||
ModifierInfo.Attribute = UMyAttributeSet::GetHealthAttribute();
|
||||
ModifierInfo.ModifierOp = EGameplayModOp::Additive;
|
||||
ModifierInfo.ModifierMagnitude = FScalableFloat(-25.0f); // -25 health
|
||||
|
||||
Modifiers.Add(ModifierInfo);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Apply Gameplay Effect
|
||||
|
||||
```cpp
|
||||
// Apply damage to target
|
||||
if (UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Target)) {
|
||||
FGameplayEffectContextHandle EffectContext = AbilitySystemComponent->MakeEffectContext();
|
||||
EffectContext.AddSourceObject(this);
|
||||
|
||||
FGameplayEffectSpecHandle SpecHandle = AbilitySystemComponent->MakeOutgoingSpec(
|
||||
UGE_Damage::StaticClass(), 1, EffectContext);
|
||||
|
||||
if (SpecHandle.IsValid()) {
|
||||
AbilitySystemComponent->ApplyGameplayEffectSpecToTarget(*SpecHandle.Data.Get(), TargetASC);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Gameplay Tags
|
||||
|
||||
### Define Tags
|
||||
|
||||
`Project Settings > Project > Gameplay Tags > Gameplay Tag List`
|
||||
|
||||
Example hierarchy:
|
||||
```
|
||||
Ability
|
||||
├─ Ability.Attack
|
||||
│ ├─ Ability.Attack.Melee
|
||||
│ └─ Ability.Attack.Ranged
|
||||
├─ Ability.Defend
|
||||
└─ Ability.Utility
|
||||
|
||||
Status
|
||||
├─ Status.Stunned
|
||||
├─ Status.Invulnerable
|
||||
└─ Status.Silenced
|
||||
```
|
||||
|
||||
### Use Tags in Abilities
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class UGA_MeleeAttack : public UGameplayAbility {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGA_MeleeAttack() {
|
||||
// This ability has these tags
|
||||
AbilityTags.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack.Melee")));
|
||||
|
||||
// Block these tags while active
|
||||
BlockAbilitiesWithTag.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Attack")));
|
||||
|
||||
// Cancel these abilities when activated
|
||||
CancelAbilitiesWithTag.AddTag(FGameplayTag::RequestGameplayTag(FName("Ability.Defend")));
|
||||
|
||||
// Can't activate if target has these tags
|
||||
ActivationBlockedTags.AddTag(FGameplayTag::RequestGameplayTag(FName("Status.Stunned")));
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cooldowns & Costs
|
||||
|
||||
### Add Cooldown
|
||||
|
||||
```cpp
|
||||
// In Ability Blueprint or C++:
|
||||
// Create Gameplay Effect with Duration = Cooldown time
|
||||
// Assign to Ability > Cooldown Gameplay Effect Class
|
||||
```
|
||||
|
||||
### Add Cost (Mana)
|
||||
|
||||
```cpp
|
||||
// Create Gameplay Effect that reduces Mana
|
||||
// Assign to Ability > Cost Gameplay Effect Class
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Get Current Attribute Value
|
||||
|
||||
```cpp
|
||||
float CurrentHealth = AbilitySystemComponent->GetNumericAttribute(UMyAttributeSet::GetHealthAttribute());
|
||||
```
|
||||
|
||||
### Listen for Attribute Changes
|
||||
|
||||
```cpp
|
||||
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(UMyAttributeSet::GetHealthAttribute())
|
||||
.AddUObject(this, &AMyCharacter::OnHealthChanged);
|
||||
|
||||
void AMyCharacter::OnHealthChanged(const FOnAttributeChangeData& Data) {
|
||||
UE_LOG(LogTemp, Warning, TEXT("Health: %f"), Data.NewValue);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/gameplay-ability-system-for-unreal-engine/
|
||||
- https://github.com/tranek/GASDocumentation (community guide)
|
||||
321
docs/engine-reference/unreal/plugins/gameplay-camera-system.md
Normal file
321
docs/engine-reference/unreal/plugins/gameplay-camera-system.md
Normal file
@@ -0,0 +1,321 @@
|
||||
# Unreal Engine 5.7 — Gameplay Camera System
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Status:** ⚠️ Experimental (introduced in UE 5.5)
|
||||
**Plugin:** `GameplayCameras` (built-in, enable in Plugins)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Gameplay Camera System** is a modular camera management framework introduced in UE 5.5.
|
||||
It replaces traditional camera setups with a flexible, node-based system that handles
|
||||
camera modes, blending, and context-aware camera behavior.
|
||||
|
||||
**Use Gameplay Cameras for:**
|
||||
- Dynamic camera behavior (3rd person, aiming, vehicles, cinematic)
|
||||
- Context-aware camera switching (combat, exploration, dialogue)
|
||||
- Smooth camera blending between modes
|
||||
- Procedural camera motion (camera shake, lag, offset)
|
||||
|
||||
**⚠️ Warning:** This plugin is experimental in UE 5.5-5.7. Expect API changes in future versions.
|
||||
|
||||
---
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### 1. **Camera Rig**
|
||||
- Defines camera configuration (position, rotation, FOV, etc.)
|
||||
- Modular node graph (similar to Material Editor)
|
||||
|
||||
### 2. **Camera Director**
|
||||
- Manages which camera rig is active
|
||||
- Handles blending between camera rigs
|
||||
|
||||
### 3. **Camera Nodes**
|
||||
- Building blocks for camera behavior:
|
||||
- **Position Nodes**: Orbit, Follow, Fixed Position
|
||||
- **Rotation Nodes**: Look At, Match Actor Rotation
|
||||
- **Modifiers**: Camera Shake, Lag, Offset
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Enable Plugin
|
||||
|
||||
`Edit > Plugins > Gameplay Cameras > Enabled > Restart`
|
||||
|
||||
### 2. Add Camera Component
|
||||
|
||||
```cpp
|
||||
#include "GameplayCameras/Public/GameplayCameraComponent.h"
|
||||
|
||||
UCLASS()
|
||||
class AMyCharacter : public ACharacter {
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AMyCharacter() {
|
||||
// Create camera component
|
||||
CameraComponent = CreateDefaultSubobject<UGameplayCameraComponent>(TEXT("GameplayCamera"));
|
||||
CameraComponent->SetupAttachment(RootComponent);
|
||||
}
|
||||
|
||||
protected:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Camera")
|
||||
TObjectPtr<UGameplayCameraComponent> CameraComponent;
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Create Camera Rig
|
||||
|
||||
### 1. Create Camera Rig Asset
|
||||
|
||||
1. Content Browser > Gameplay > Gameplay Camera Rig
|
||||
2. Open Camera Rig Editor (node-based graph)
|
||||
|
||||
### 2. Build Camera Rig (Example: Third Person)
|
||||
|
||||
**Node Setup:**
|
||||
```
|
||||
Actor Position (Character)
|
||||
↓
|
||||
Orbit Node (Orbit around character)
|
||||
↓
|
||||
Offset Node (Shoulder offset)
|
||||
↓
|
||||
Look At Node (Look at character)
|
||||
↓
|
||||
Camera Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Camera Nodes
|
||||
|
||||
### Position Nodes
|
||||
|
||||
#### Orbit Node (Third Person)
|
||||
- Orbits around target actor
|
||||
- Configure:
|
||||
- **Orbit Distance**: Distance from target (e.g., 300 units)
|
||||
- **Pitch Range**: Min/Max pitch angles
|
||||
- **Yaw Range**: Min/Max yaw angles
|
||||
|
||||
#### Follow Node (Smooth Follow)
|
||||
- Follows target with lag
|
||||
- Configure:
|
||||
- **Lag Speed**: How quickly camera catches up
|
||||
- **Offset**: Fixed offset from target
|
||||
|
||||
#### Fixed Position Node
|
||||
- Static camera position in world space
|
||||
|
||||
---
|
||||
|
||||
### Rotation Nodes
|
||||
|
||||
#### Look At Node
|
||||
- Points camera at target
|
||||
- Configure:
|
||||
- **Target**: Actor or component to look at
|
||||
- **Offset**: Look-at offset (e.g., aim at head instead of feet)
|
||||
|
||||
#### Match Actor Rotation
|
||||
- Matches target actor's rotation
|
||||
- Useful for first-person or vehicle cameras
|
||||
|
||||
---
|
||||
|
||||
### Modifier Nodes
|
||||
|
||||
#### Camera Shake
|
||||
- Adds procedural shake (e.g., footsteps, explosions)
|
||||
- Configure:
|
||||
- **Shake Pattern**: Perlin noise, sine wave, custom
|
||||
- **Amplitude**: Shake strength
|
||||
|
||||
#### Camera Lag
|
||||
- Smooth dampening of camera movement
|
||||
- Configure:
|
||||
- **Lag Speed**: Damping factor (0 = instant, higher = more lag)
|
||||
|
||||
#### Offset Node
|
||||
- Static offset from calculated position
|
||||
- Useful for shoulder camera offset
|
||||
|
||||
---
|
||||
|
||||
## Camera Director (Switching Between Rigs)
|
||||
|
||||
### Assign Camera Rig
|
||||
|
||||
```cpp
|
||||
#include "GameplayCameras/Public/GameplayCameraComponent.h"
|
||||
|
||||
void AMyCharacter::SetCameraMode(UGameplayCameraRig* NewRig) {
|
||||
if (CameraComponent) {
|
||||
CameraComponent->SetCameraRig(NewRig);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Blend Between Camera Rigs
|
||||
|
||||
```cpp
|
||||
// Blend to aiming camera over 0.5 seconds
|
||||
CameraComponent->BlendToCameraRig(AimingCameraRig, 0.5f);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Example: Third Person + Aiming
|
||||
|
||||
### 1. Create Two Camera Rigs
|
||||
|
||||
**Third Person Rig:**
|
||||
```
|
||||
Actor Position → Orbit (distance: 300) → Look At → Output
|
||||
```
|
||||
|
||||
**Aiming Rig:**
|
||||
```
|
||||
Actor Position → Orbit (distance: 150) → Offset (shoulder) → Look At → Output
|
||||
```
|
||||
|
||||
### 2. Switch on Aim
|
||||
|
||||
```cpp
|
||||
UPROPERTY(EditAnywhere, Category = "Camera")
|
||||
TObjectPtr<UGameplayCameraRig> ThirdPersonRig;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category = "Camera")
|
||||
TObjectPtr<UGameplayCameraRig> AimingRig;
|
||||
|
||||
void StartAiming() {
|
||||
CameraComponent->BlendToCameraRig(AimingRig, 0.3f); // Blend over 0.3s
|
||||
}
|
||||
|
||||
void StopAiming() {
|
||||
CameraComponent->BlendToCameraRig(ThirdPersonRig, 0.3f);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Over-the-Shoulder Camera
|
||||
|
||||
```
|
||||
Actor Position
|
||||
↓
|
||||
Orbit Node (distance: 250, yaw offset: 30°)
|
||||
↓
|
||||
Offset Node (X: 0, Y: 50, Z: 50) // Shoulder offset
|
||||
↓
|
||||
Look At Node (target: Character head)
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Vehicle Camera
|
||||
|
||||
```
|
||||
Vehicle Position
|
||||
↓
|
||||
Follow Node (lag: 0.2)
|
||||
↓
|
||||
Offset Node (behind vehicle: X: -400, Z: 150)
|
||||
↓
|
||||
Look At Node (target: Vehicle)
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### First Person Camera
|
||||
|
||||
```
|
||||
Character Head Socket
|
||||
↓
|
||||
Match Actor Rotation
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Camera Shake
|
||||
|
||||
### Trigger Camera Shake
|
||||
|
||||
```cpp
|
||||
#include "GameplayCameras/Public/GameplayCameraShake.h"
|
||||
|
||||
void TriggerExplosionShake() {
|
||||
if (APlayerController* PC = GetWorld()->GetFirstPlayerController()) {
|
||||
if (UGameplayCameraComponent* CameraComp = PC->FindComponentByClass<UGameplayCameraComponent>()) {
|
||||
CameraComp->PlayCameraShake(ExplosionShakeClass, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tips
|
||||
|
||||
- Limit camera shake frequency (don't trigger every frame)
|
||||
- Use camera lag sparingly (expensive for high lag values)
|
||||
- Cache camera rig references (don't search every frame)
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### Camera Debug Visualization
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// GameplayCameras.Debug 1 - Show active camera rig info
|
||||
// showdebug camera - Show camera debug info
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration from Legacy Cameras
|
||||
|
||||
### Old Spring Arm + Camera Component
|
||||
|
||||
```cpp
|
||||
// ❌ OLD: Spring Arm Component
|
||||
USpringArmComponent* SpringArm;
|
||||
UCameraComponent* Camera;
|
||||
|
||||
// ✅ NEW: Gameplay Camera Component
|
||||
UGameplayCameraComponent* CameraComponent;
|
||||
// Build orbit + look-at rig in Camera Rig asset
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Limitations (Experimental Status)
|
||||
|
||||
- **API Instability**: Expect breaking changes in UE 5.8+
|
||||
- **Limited Documentation**: Official docs still evolving
|
||||
- **Blueprint Support**: Primarily C++ focused (Blueprint support improving)
|
||||
- **Production Risk**: Test thoroughly before shipping
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/gameplay-cameras-in-unreal-engine/
|
||||
- UE 5.5+ Release Notes
|
||||
- **Note:** This system is experimental. Always check latest official docs for API changes.
|
||||
356
docs/engine-reference/unreal/plugins/pcg.md
Normal file
356
docs/engine-reference/unreal/plugins/pcg.md
Normal file
@@ -0,0 +1,356 @@
|
||||
# Unreal Engine 5.7 — PCG (Procedural Content Generation)
|
||||
|
||||
**Last verified:** 2026-02-13
|
||||
**Status:** Production-Ready (as of UE 5.7)
|
||||
**Plugin:** `PCG` (built-in, enable in Plugins)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Procedural Content Generation (PCG)** is Unreal's node-based framework for generating
|
||||
procedural content at massive scale. It's designed for populating large open worlds with
|
||||
foliage, rocks, props, buildings, and other environmental detail.
|
||||
|
||||
**Use PCG for:**
|
||||
- Procedural foliage placement (trees, grass, rocks)
|
||||
- Biome-based environment generation
|
||||
- Road/path generation
|
||||
- Building/structure placement
|
||||
- World detail population (props, clutter)
|
||||
|
||||
**DON'T use PCG for:**
|
||||
- Gameplay logic (use Blueprints/C++)
|
||||
- One-off manual placement (use editor tools)
|
||||
|
||||
**⚠️ Note:** PCG was experimental in UE 5.0-5.6, became production-ready in UE 5.7.
|
||||
|
||||
---
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### 1. **PCG Graph**
|
||||
- Node-based graph (similar to Material Editor)
|
||||
- Defines generation rules
|
||||
|
||||
### 2. **PCG Component**
|
||||
- Placed in level, executes PCG Graph
|
||||
- Generates content in defined volume
|
||||
|
||||
### 3. **PCG Data**
|
||||
- Point data (positions, rotations, scales)
|
||||
- Spline data (paths, roads, rivers)
|
||||
- Volume data (density, biome masks)
|
||||
|
||||
### 4. **Nodes**
|
||||
- **Samplers**: Generate points (Grid, Poisson, Surface)
|
||||
- **Filters**: Remove points based on rules (Density, Tag, Bounds)
|
||||
- **Modifiers**: Transform points (Offset, Rotate, Scale)
|
||||
- **Spawners**: Instantiate meshes/actors at points
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Enable Plugin
|
||||
|
||||
`Edit > Plugins > PCG > Enabled > Restart`
|
||||
|
||||
### 2. Create PCG Volume
|
||||
|
||||
1. Place Actors > Volumes > PCG Volume
|
||||
2. Scale volume to desired generation area
|
||||
|
||||
### 3. Create PCG Graph
|
||||
|
||||
1. Content Browser > PCG > PCG Graph
|
||||
2. Open PCG Graph Editor
|
||||
|
||||
---
|
||||
|
||||
## Basic Workflow
|
||||
|
||||
### Example: Forest Generation
|
||||
|
||||
#### 1. Create PCG Graph
|
||||
|
||||
**Node Setup:**
|
||||
```
|
||||
Input (Volume)
|
||||
↓
|
||||
Surface Sampler (sample volume surface, points per m²: 0.5)
|
||||
↓
|
||||
Density Filter (use texture mask or noise)
|
||||
↓
|
||||
Static Mesh Spawner (tree meshes)
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
#### 2. Assign Graph to Volume
|
||||
|
||||
1. Select PCG Volume
|
||||
2. Details Panel > PCG Component > Graph = Your PCG Graph
|
||||
3. Click "Generate" button
|
||||
|
||||
---
|
||||
|
||||
## Key Node Types
|
||||
|
||||
### Samplers (Point Generation)
|
||||
|
||||
#### Grid Sampler
|
||||
- Regular grid of points
|
||||
- Configure:
|
||||
- **Grid Size**: Distance between points
|
||||
- **Offset**: Random offset per point
|
||||
|
||||
#### Poisson Disk Sampler
|
||||
- Random points with minimum distance
|
||||
- Configure:
|
||||
- **Points Per m²**: Density
|
||||
- **Min Distance**: Spacing between points
|
||||
|
||||
#### Surface Sampler
|
||||
- Points on mesh surfaces or landscape
|
||||
- Configure:
|
||||
- **Points Per m²**: Density
|
||||
- **Surface Only**: Only surface, not volume
|
||||
|
||||
---
|
||||
|
||||
### Filters (Point Removal)
|
||||
|
||||
#### Density Filter
|
||||
- Remove points based on density value
|
||||
- Input: Texture or noise
|
||||
- Use for: Biome masks, clearings, paths
|
||||
|
||||
#### Tag Filter
|
||||
- Filter points by tag
|
||||
- Use for: Conditional spawning
|
||||
|
||||
#### Bounds Filter
|
||||
- Keep only points within bounds
|
||||
- Use for: Limiting generation to specific areas
|
||||
|
||||
---
|
||||
|
||||
### Modifiers (Point Transformation)
|
||||
|
||||
#### Rotate
|
||||
- Randomize point rotation
|
||||
- Configure:
|
||||
- **Min/Max Rotation**: Rotation range per axis
|
||||
|
||||
#### Scale
|
||||
- Randomize point scale
|
||||
- Configure:
|
||||
- **Min/Max Scale**: Scale range
|
||||
|
||||
#### Project to Ground
|
||||
- Snap points to landscape surface
|
||||
|
||||
---
|
||||
|
||||
### Spawners (Mesh/Actor Instantiation)
|
||||
|
||||
#### Static Mesh Spawner
|
||||
- Spawn static meshes at points
|
||||
- Configure:
|
||||
- **Mesh List**: Array of meshes (random selection)
|
||||
- **Culling Distance**: LOD/culling settings
|
||||
|
||||
#### Actor Spawner
|
||||
- Spawn Blueprint actors at points
|
||||
- Use for: Gameplay actors, interactive objects
|
||||
|
||||
---
|
||||
|
||||
## Data Sources
|
||||
|
||||
### Landscape
|
||||
- Use landscape as input for sampling
|
||||
- Automatically projects to landscape height
|
||||
|
||||
### Splines
|
||||
- Generate content along splines (roads, rivers, paths)
|
||||
- Example: Trees along path
|
||||
|
||||
### Textures
|
||||
- Use textures as density masks
|
||||
- Paint biomes, clearings, areas
|
||||
|
||||
---
|
||||
|
||||
## Biome Example (Mixed Forest)
|
||||
|
||||
### Graph Setup
|
||||
|
||||
```
|
||||
Input (Landscape)
|
||||
↓
|
||||
Surface Sampler (density: 1.0)
|
||||
↓
|
||||
┌─────────────────┬─────────────────┐
|
||||
│ Tree Biome │ Rock Biome │
|
||||
│ (density > 0.5) │ (density < 0.5) │
|
||||
├─────────────────┼─────────────────┤
|
||||
│ Tree Spawner │ Rock Spawner │
|
||||
└─────────────────┴─────────────────┘
|
||||
↓
|
||||
Merge
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Spline-Based Generation (Road with Trees)
|
||||
|
||||
### 1. Create PCG Graph
|
||||
|
||||
```
|
||||
Spline Input
|
||||
↓
|
||||
Spline Sampler (sample along spline)
|
||||
↓
|
||||
Offset (offset from spline path)
|
||||
↓
|
||||
Tree Spawner
|
||||
↓
|
||||
Output
|
||||
```
|
||||
|
||||
### 2. Add Spline Component to PCG Volume
|
||||
|
||||
1. PCG Volume > Add Component > Spline
|
||||
2. Draw spline path
|
||||
3. PCG Graph reads spline data
|
||||
|
||||
---
|
||||
|
||||
## Runtime Generation
|
||||
|
||||
### Trigger Generation from C++
|
||||
|
||||
```cpp
|
||||
#include "PCGComponent.h"
|
||||
|
||||
UPCGComponent* PCGComp = /* Get PCG Component */;
|
||||
PCGComp->Generate(); // Execute PCG graph
|
||||
```
|
||||
|
||||
### Stream Generation (Large Worlds)
|
||||
|
||||
- PCG automatically streams with World Partition
|
||||
- Only generates content in loaded cells
|
||||
|
||||
---
|
||||
|
||||
## Performance
|
||||
|
||||
### Optimization Tips
|
||||
|
||||
- Use **culling distance** on spawned meshes (LOD)
|
||||
- Limit **density** (fewer points = better performance)
|
||||
- Use **Hierarchical Instanced Static Meshes (HISM)** for repeated meshes
|
||||
- Enable **streaming** for large worlds
|
||||
|
||||
### Debug Performance
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// pcg.graph.debug 1 - Show PCG debug info
|
||||
// stat pcg - Show PCG performance stats
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Forest with Clearings
|
||||
|
||||
```
|
||||
Surface Sampler
|
||||
↓
|
||||
Density Filter (noise texture with clearings)
|
||||
↓
|
||||
Tree Spawner (pine, oak, birch)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Rocks on Steep Slopes
|
||||
|
||||
```
|
||||
Landscape Input
|
||||
↓
|
||||
Surface Sampler
|
||||
↓
|
||||
Slope Filter (angle > 30°)
|
||||
↓
|
||||
Rock Spawner
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Props Along Road
|
||||
|
||||
```
|
||||
Spline Input (road spline)
|
||||
↓
|
||||
Spline Sampler
|
||||
↓
|
||||
Offset (side of road)
|
||||
↓
|
||||
Street Light Spawner
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Debugging
|
||||
|
||||
### PCG Debug Visualization
|
||||
|
||||
```cpp
|
||||
// Console commands:
|
||||
// pcg.debug.display 1 - Show points and generation bounds
|
||||
// pcg.debug.colormode points - Color-code points
|
||||
```
|
||||
|
||||
### Graph Debugging
|
||||
|
||||
- PCG Graph Editor > Debug > Show Debug Points
|
||||
- Visualize points at each node in the graph
|
||||
|
||||
---
|
||||
|
||||
## Migration from UE 5.6 (Experimental) to 5.7 (Production)
|
||||
|
||||
### API Changes
|
||||
|
||||
```cpp
|
||||
// ❌ OLD (5.6 experimental API):
|
||||
// Some nodes renamed, API unstable
|
||||
|
||||
// ✅ NEW (5.7 production API):
|
||||
// Stable node types, documented API
|
||||
```
|
||||
|
||||
**Migration:** Rebuild PCG graphs using stable 5.7 nodes. Test thoroughly.
|
||||
|
||||
---
|
||||
|
||||
## Limitations
|
||||
|
||||
- **Not for gameplay logic**: Use Blueprints/C++ for game rules
|
||||
- **Large graphs can be slow**: Optimize with filters and density reduction
|
||||
- **Runtime generation overhead**: Pre-generate when possible
|
||||
|
||||
---
|
||||
|
||||
## Sources
|
||||
- https://docs.unrealengine.com/5.7/en-US/procedural-content-generation-in-unreal-engine/
|
||||
- https://docs.unrealengine.com/5.7/en-US/pcg-quick-start-in-unreal-engine/
|
||||
- UE 5.7 Release Notes (PCG Production-Ready announcement)
|
||||
Reference in New Issue
Block a user