10 KiB
10 KiB
69 — BPC_PerformanceScaler
Blueprint Spec — UE 5.5–5.7
Parent Class
ActorComponent
Dependencies
BPC_LightingManager— Controls light qualityBPC_AudioManager— Controls audio qualityBPC_VFXManager— Controls particle LODBPC_AtmosphereController— Preset complexity reductionSS_SaveManager— Save performance settingsGI_GameFramework— Frame time measurement
Purpose
Automatically adjusts graphics, audio, and gameplay quality settings based on real-time performance metrics (frame time, draw calls, memory usage). Provides a unified interface for all other systems to scale their quality without direct awareness of the hardware. Supports manual user override via Settings menu and adaptive automatic mode. Maintains a performance budget that is dynamically allocated across subsystems.
Enums
EPerformanceQualityLevel
| Value | Description |
|---|---|
| Low | Minimum quality, max performance |
| Medium | Balanced quality/performance |
| High | High quality |
| Ultra | Maximum quality, no compromises |
| Cinematic | Maximum visual fidelity, 30fps target |
EScalingTarget
| Value | Description |
|---|---|
| ResolutionScale | Screen percentage |
| ShadowQuality | Shadow resolution and distance |
| TextureQuality | Texture streaming pool |
| PostProcessQuality | Post-process complexity |
| ParticleLOD | VFX particle count |
| AudioQuality | Audio layer count |
| ViewDistance | Draw distance |
| FoliageDensity | Foliage and grass density |
| AntiAliasing | Anti-aliasing method |
| GlobalIllumination | GI quality |
Variables
| Name | Type | Description |
|---|---|---|
CurrentQualityLevel |
EPerformanceQualityLevel | Active quality level |
TargetQualityLevel |
EPerformanceQualityLevel | Quality being transitioned to |
bAdaptiveMode |
Bool | Auto-adjust based on performance |
bUserOverride |
Bool | Player manually set quality |
FrameTimeHistory |
TArray<Float> | Rolling frame time samples |
AverageFrameTime |
Float | Smoothed average frame time |
FrameTimeVariance |
Float | Frame time stability metric |
TargetFrameTime |
Float | Desired frame time (e.g., 16.67ms for 60fps) |
PerformanceBudget |
Float | Allowed ms per frame |
ScalerSettings |
TMap<EScalingTarget, float> | Current scaling multipliers |
bIsScalingInProgress |
Bool | Currently adjusting settings |
MeasurementInterval |
Float | Seconds between performance checks |
AdjustmentCooldown |
Float | Min time between quality changes |
LastAdjustmentTime |
Float | Last quality change timestamp |
QualityOverrideLevel |
EPerformanceQualityLevel | Manual override level |
PlatformProfile |
FName | Detected platform profile |
Functions
| Name | Inputs | Outputs | Description |
|---|---|---|---|
Initialize |
— | — | Read saved settings, detect platform |
SetQualityLevel |
Level: EPerformanceQualityLevel | — | Apply quality level |
SetAdaptiveMode |
bEnabled: Bool | — | Toggle adaptive scaling |
GetCurrentQualityLevel |
— | EPerformanceQualityLevel | Current level |
GetRecommendedQuality |
— | EPerformanceQualityLevel | System-recommended level |
MeasurePerformance |
— | — | Sample frame time from GI_GameFramework |
EvaluateScaling |
— | — | Decide if scaling is needed |
ApplyScalerSettings |
Level: EPerformanceQualityLevel | — | Apply settings to subsystems |
SetResolutionScale |
Scale: Float | — | Screen percentage |
SetShadowQuality |
Level: Int32 | — | Shadow resolution preset |
SetTexturePoolSize |
SizeMB: Int32 | — | Texture streaming pool |
SetViewDistance |
Distance: Float | — | Draw distance |
SetFoliageDensity |
Density: Float | — | Foliage cull distance |
SetParticleLOD |
LODLevel: Int32 | — | Particle LOD for VFXManager |
SetAudioQuality |
Quality: Int32 | — | Audio layer count |
SetGlobalIllumination |
Quality: Int32 | — | GI method |
NotifySubsystemScaled |
Target: EScalingTarget | — | Broadcast scaled subsystems |
SavePerformanceSettings |
— | — | Persist to SS_SaveManager |
OnFrameTimeSpike |
SpikeValue: Float | — | Handle sudden frame drop |
Blueprint Flow
[BeginPlay]
└─► Initialize():
Detect platform (Console, PC Low/Med/High, Steam Deck, etc.)
Load saved settings from SS_SaveManager
If no saved settings:
GetRecommendedQuality() based on platform
Apply quality level
Start measurement timer with MeasurementInterval
[Timer - MeasurePerformance]
└─► MeasurePerformance():
Get frame time from GI_GameFramework.FrameTimeHistory
Add to local FrameTimeHistory, keep rolling window (last 60 frames)
Calculate AverageFrameTime (exponential moving average)
Calculate FrameTimeVariance (standard deviation of history)
If bAdaptiveMode and not bUserOverride:
EvaluateScaling()
[EvaluateScaling]
└─► If AverageFrameTime > TargetFrameTime * 1.2:
(Running slow, too many frames over target)
If TimeSince LastAdjustment > AdjustmentCooldown:
SetQualityLevel(CurrentQualityLevel - 1)
└─► If AverageFrameTime < TargetFrameTime * 0.7 and FrameTimeVariance < 2.0:
(Running fast, stable, can upgrade)
If TimeSince LastAdjustment > AdjustmentCooldown * 2:
SetQualityLevel(CurrentQualityLevel + 1)
└─► If FrameTimeVariance > 5.0:
(Unstable frame times, reduce quality for stability)
SetQualityLevel(CurrentQualityLevel - 1)
[SetQualityLevel]
└─► If CurrentQualityLevel == Level: return
└─► TargetQualityLevel = Level
└─► bIsScalingInProgress = true
└─► ApplyScalerSettings(Level)
└─► For each subsystem:
BPC_LightingManager: SetParticleLOD mapped to QualityLevel
BPC_AudioManager: Reduce active layers and spatial audio
BPC_VFXManager: SetParticleLOD mapped to QualityLevel
BPC_AtmosphereController: Reduce preset complexity
└─► Apply UE console variables for resolution, shadows, textures, foliage
└─► bIsScalingInProgress = false
└─► CurrentQualityLevel = TargetQualityLevel
└─► OnQualityLevelChanged.Broadcast(CurrentQualityLevel)
└─► SavePerformanceSettings()
[ApplyScalerSettings - Quality Levels]
└─► Low:
ResolutionScale = 0.7
ShadowQuality = 0 (off/low)
TexturePoolSize = 512 MB
PostProcessQuality = Low
ParticleLOD = 2 (minimum)
AudioQuality = 0 (mono, 2 layers max)
ViewDistance = Low
FoliageDensity = 0.3
AntiAliasing = TSR Low
GlobalIllumination = None
└─► Medium:
ResolutionScale = 0.85
ShadowQuality = 1 (medium)
TexturePoolSize = 1024 MB
PostProcessQuality = Medium
ParticleLOD = 1 (reduced)
AudioQuality = 1 (stereo, 4 layers)
ViewDistance = Medium
FoliageDensity = 0.6
AntiAliasing = TSR Medium
GlobalIllumination = Lumen Low
└─► High:
ResolutionScale = 1.0
ShadowQuality = 2 (high)
TexturePoolSize = 2048 MB
PostProcessQuality = High
ParticleLOD = 0 (full)
AudioQuality = 2 (surround, all layers)
ViewDistance = High
FoliageDensity = 1.0
AntiAliasing = TSR High
GlobalIllumination = Lumen High
└─► Ultra:
ResolutionScale = 1.0
ShadowQuality = 3 (ultra)
TexturePoolSize = 4096 MB
PostProcessQuality = Cinematic
ParticleLOD = 0 (full with extras)
AudioQuality = 3 (full spatial, max layers)
ViewDistance = Epic
FoliageDensity = 1.5
AntiAliasing = TSR Epic
GlobalIllumination = Lumen Ultra
└─► Cinematic:
ResolutionScale = 1.0 (or 1.25 for supersampling)
ShadowQuality = 3 (ultra with contact shadows)
TexturePoolSize = 8192 MB
PostProcessQuality = Cinematic with extra effects
ParticleLOD = 0 with extra presets
AudioQuality = 3
ViewDistance = Epic with forced high-resolution impostors
FoliageDensity = 2.0
AntiAliasing = TSR Epic with extra samples
GlobalIllumination = Lumen Ultra + Path Tracing toggle
[OnFrameTimeSpike]
└─► If spike > 50ms (sudden freeze):
SetQualityLevel(Low) temporarily
After 5 seconds of stable performance:
Gradually restore to previous level
Event Dispatchers
| Name | Payload | Description |
|---|---|---|
OnQualityLevelChanged |
NewLevel: EPerformanceQualityLevel | Broadcast quality change |
OnScalingTargetAdjusted |
Target: EScalingTarget, NewValue: Float | Per-target adjustment |
Communications With
| Target | Method | Why |
|---|---|---|
GI_GameFramework |
Direct call | Frame time data source |
SS_SaveManager |
Direct call | Save/load settings |
BPC_LightingManager |
Get from player | Light quality reduction |
BPC_AudioManager |
Get from player | Audio quality reduction |
BPC_VFXManager |
Get from player | Particle LOD control |
BPC_AtmosphereController |
Get from player | Preset complexity reduction |
WBP_SettingsUI |
Event | User quality override |
[BPC_PlayerController] |
Cast | Console command execution |
Reuse Notes
- Works with any subsystem that exposes quality API: Lighting, Audio, VFX, etc.
- Frame time history rolling window: last 60 frames for smooth average
- Adaptive mode is off by default; user must enable in settings
- User override locks quality level until adaptive mode is re-enabled
- PlatformProfile stores detected hardware for initial recommendation
- Adjustment cooldown prevents oscillation between quality levels
- Per-scaling-target notifications enable UI to show specific quality changes