A functional core OSS version is available on GitHub: https://github.com/gregorik/PSO-Autopilot. The present Fab version is fully featured, including all USP's described in the manual.
PSO Autopilot is a reliable, production-ready solution to Unreal Engine 5's notorious shader compilation stutter and lag.
The "Shader Compilation" plugins on various marketplaces attempt to solve stutter by brute-forcing the Engine: loading all of your project's assets into memory simultaneously. If you are building a massive 50GB open-world game, this simplistic approach guarantees catastrophic RAM spikes, completely frozen loading screens, and eventually, Out-Of-Memory (OOM) crashes on consoles or lower-end PCs.
PSO Autopilot is different:it was created from the ground up to orchestrate Unreal's native hardware pipeline asynchronously, managing memory, threads, and driver caches with architectural precision.
Core functionality deep-dive:
Memory-Safe Chunking: The plugin uses FStreamableManager to asynchronously load constrained batches of assets (default 100). It unloads them and explicitly forces Garbage Collection (GEngine->ForceGarbageCollection) between batches, which effectively mitigates Out-Of-Memory (OOM) crashes on large projects.
Time-Sliced Game Thread Yielding: The ProcessBatchTimeSliced() function respects the MaxProcessingTimeMsPerFrame budget (default 5ms), breaking up the workload and yielding the Game Thread to keep UI animations smooth.
Smart Cache Skipping: The plugin generates an MD5 fingerprint to bypass redundant warmups on subsequent boots by reading/writing to GGameUserSettingsIni.
Engine PSO Pacing: It checks FShaderPipelineCache::NumPrecompilesRemaining() to ensure it doesn't overrun the engine's built-in background shader compilation queue.
Empty FName poisoning in asset queries - An empty DirectoriesToScan entry (Path="") in DefaultGame.ini silently injected an empty FName into FARFilter::PackagePaths, causing GetAssets() to return zero results with no error. Added an IsEmpty() guard in ScanForAssets() and removed the poisoned config line.
Asset registry race condition in -game mode - IsLoadingAssets() returned false before the background asset gatherer had even started, producing an empty scan. Added Registry.SearchAllAssets(true) to force synchronous registry population before querying.
Non-material assets silently skipped - ForceAssetWarmup() only handled UMaterialInterface directly. Meshes, particle systems, and other assets referencing materials were ignored. Replaced the raw property scan with FReferenceFinder to extract all referenced UMaterialInterface objects from any loaded asset.
BootLoader delegate leak - APSOAutopilotBootLoader had no EndPlay override. Subsystem delegates were never unbound on actor destruction, leading to dangling callbacks and potential crashes on level transitions. Added proper delegate unbinding in EndPlay.
High-Priority Fixes
Dead code removal - Removed ~50 lines of unreachable BuildWarmupFingerprint() declaration and implementation that had been superseded by the async thread-pool fingerprint computation.
Missing StopWarmup() method - There was no way to cancel an in-progress warmup. Added StopWarmup() as a BlueprintCallable method that resets the state machine, releases loaded assets, and broadcasts completion.
Fragile material extraction via raw property iteration - The original ForceAssetWarmup walked UObject properties manually to find material references, which was brittle across engine versions. Replaced with the engine's FReferenceFinder utility for robust, recursive reference discovery.
Untracked forced-streaming textures - Textures forced into VRAM via SetForceMipLevelsToBeResident() were never tracked. Added ForcedStreamingTextures tracking set so residency can be refreshed or released post-warmup (60-second extended residency applied on completion).
Medium-Priority Fixes
Fingerprint future timeout - The async fingerprint computation on the thread pool had no timeout guard. If the thread pool stalled, the subsystem would hang indefinitely in the Fingerprinting state. Added a 10-second timeout with fallback to force a full warmup on timeout.
CDO settings mutations stacking across PIE runs - APSOAutopilotDemoManager mutated the settings CDO (Class Default Object) directly without calling ReloadConfig() first. Settings overrides from previous runs accumulated. Added ReloadConfig() before applying overrides to start from clean defaults each run.
Custom HUDClass ignored during forced validation - When bForceValidationRun was true, the demo manager always spawned the default widget, ignoring any user-specified HUDClass. Fixed to respect the configured HUD class in all code paths.
StartWarmup re-entry from Finished state - The state guard only checked CurrentState != EPSOWarmupState::Idle, but a completed warmup left the state at Finished. Calling StartWarmup() again was silently rejected. Updated the guard to allow restart from both Idle and Finished states.
Deprecated GetUsedTextures 5-parameter API - UE 5.7 changed the GetUsedTextures signature, producing compiler warnings. Updated to the current 4-parameter overload.
Low-Priority Fixes
CanContainContent: true with empty Content directory - The .uplugin declared CanContainContent: true but the plugin ships no content assets. Set to false to avoid Fab validator warnings and unnecessary Content directory expectations.
Virtual Texture preheat incomplete - UVirtualTexture2D assets were discovered but UpdateResource() was never called during the streaming phase. Added explicit UpdateResource() calls and tracking via PendingVirtualTextures set to properly page virtual textures into GPU memory.
Flat spinner widget appearance - The spinner used WhiteSquareTexture which looked flat and dated. Replaced with a gradient-based circular spinner with rotation animation and pulsing opacity for a polished loading indicator.
Redundant BuildFallbackWidgetTree() calls - Both NativeConstruct implementations (DemoWidget and LoadingScreenWidget) called the fallback widget builder unconditionally, even when UMG bindings were present. Added checks to only build the C++ Slate tree when no designer-bound widgets exist.
Streaming telemetry message missing resource count - The "Waiting for texture streaming..." log message didn't include how many resources were pending. Added GetNumWantingResources() count to the status broadcast for better diagnostics.
Architecture
State machine: 10-state EPSOWarmupState enum drives all subsystem behavior through Tick().
Module loading phase: PreDefault to ensure availability before gameplay subsystems.
Async fingerprint: MD5 hash computed on thread pool (engine version + scan directories + asset paths + timestamps).
Replaced shader-cache-only warming with real PSO precache paths for warmed assets.
Added asset-specific PSO precache for primitive assets through transient static mesh and skeletal mesh components.
Added explicit material PrecachePSOs(...) fallback with local, nanite, and particle vertex factory coverage.
Switched batch completion to plugin-owned PSO request and graph-event tracking instead of waiting on the global engine precompile backlog.
Logged async load failures, counted them against the run, and blocked fingerprint persistence after any warmup failure.
Sanitized scan settings before use so blank or duplicate directories and invalid class paths cannot collapse asset discovery.
Waited for pending virtual texture initialization and streaming before marking a batch complete.
Restored mutable settings after demo and boot overrides so changes do not leak across warmup runs.
Changed
Warmup execution now uses a per-run settings snapshot instead of rereading mutable defaults mid-run.
Added the module dependencies required by the new PSO precache path.
Synced the same source changes into Plugins/PSOAutopilot, PluginBuild, and PluginStaging.
Texture streaming infinite hang — The StreamingTextures state had no timeout, so a single texture that never finished streaming could stall the entire warmup indefinitely. Added a 30-second timeout that logs a warning and advances to the next batch.
Batch load stuck-state recovery — FStreamableManager::RequestAsyncLoad could silently never complete if an asset was corrupted or had cascading dependency issues. Added a 60-second watchdog timer in the LoadingBatch state. On timeout, the pending load is cancelled, the batch is marked as failed, and processing continues with the next batch. BatchLoadStartTime tracking added to Initialize(), StartWarmup(), and BeginLoadingBatch().
Texture mip residency too short — SetForceMipLevelsToBeResident() was called with a 30-second duration, but large warmups could take several minutes. Textures loaded in early batches would drop their high-res mips before the loading screen finished. Increased to 300 seconds (5 minutes).
SearchAllAssets hitching the Editor — The synchronous Registry.SearchAllAssets(true) call (added in v1.1 for -game mode) was also running in Editor builds where it caused a multi-second hitch. Wrapped in if (!GIsEditor) guard so it only runs in standalone game mode where the async gatherer hasn't started yet.
Multi-fingerprint cache — The fingerprint system only stored a single LastCompletedFingerprint value, meaning different scan configurations (e.g., multiple Boot Loaders scanning different directories) would overwrite each other. Replaced with an LRU cache storing up to 8 completed fingerprints as a comma-separated CompletedFingerprints key. Legacy single-entry format is migrated automatically on first read.
Incomplete GC purge between batches — ForceGarbageCollection(false) only collected unreachable objects but didn't purge them from memory. Changed to ForceGarbageCollection(true) for a full purge, ensuring batch memory is actually reclaimed before the next load.
Transient mesh components parented to wrong outer — UStaticMeshComponent objects created for PSO precaching were parented to the subsystem's outer (the GameInstance), which prevented them from being garbage collected between batches. Changed to NewObject<UStaticMeshComponent>(GetTransientPackage()) so they live in the transient package and are properly cleaned up.
Boot Loader level transition crash — UGameplayStatics::OpenLevel() was called without validating that the target level exists. On a typo or missing map, this could crash or produce cryptic errors. Added FPackageName::SearchForPackageOnDisk() validation with a warning log if the level is not found.
Dead Outer parameter — After fixing transient components to use GetTransientPackage(), the UObject* Outer parameter on QueuePrimitiveAssetPSOPrecache() became unused dead code. Removed from both the function signature and all call sites.
Demo widget telemetry panel cut off — The bottom-left telemetry panel in UPSOAutopilotDemoWidget was sized too small (640x280) and positioned where it clipped off-screen. Enlarged to 920x420 and repositioned from (36,-36) to (24,-24).
Demo widget text overflow — Long status messages, cache comparison text, and metrics text overflowed the panel bounds. Added SetAutoWrapText(true) on MetricsText, CacheStatusText, and ComparisonSummaryText.
Documentation
Comprehensive manual rewrite — Expanded Docs/index.html from 595 lines to ~850 lines:
New State Machine section with visual diagram and per-state descriptions
New Fingerprint & Caching section covering MD5 hashing, editor timestamps, and multi-configuration LRU cache
New Best Practices section (targeting, batch tuning, dedicated loading levels, standalone testing)
Full Boot Loader property reference table
Configuration section rewritten with HTML tables organized by category (Targeting, Memory, Performance, Visual Continuity, Validation)
Troubleshooting FAQ expanded from 3 items to 22 items across 8 categories:
PSO Autopilot now covers more real startup scenarios by discovering warmup content from explicit roots, runtime-queued assets, and package dependencies instead of relying only on a basic directory scan.
Gameplay packages can now preload before OnWarmupComplete, which shifts more first-run cost under the loading screen instead of into the first seconds of gameplay.
The packaged demo flow now works end to end, including boot-level warmup, gameplay map preload, map handoff, and duplicate-warmup suppression on the destination map.
New in This Release
Added ExplicitAssetsToWarm for maps, blueprints, labels, and other startup-critical assets that are not guaranteed to be found through directory scanning alone.
Added PackagesToPreload so destination gameplay packages can load before the warmup sequence completes.
Added runtime APIs for dynamic startup flows:
RegisterRuntimeWarmupAsset(...)
QueuePackagePreload(...)
QueuePackagePreloadByName(...)
Added dependency-expansion controls:
bExpandPackageDependencies
DependencyExpansionDepth
bIncludeSoftPackageReferences
bIncludeManagementReferences
Added a PreloadingPackages warmup state, retained-package tracking, and preload telemetry so package loading is treated as a first-class part of startup warmup.
Added boot-loader controls for destination-level warmup seeding and package preload:
bRegisterLevelAsWarmupSeed
ExplicitWarmupAssetsOnBeginPlay
PackagesToPreloadOnBeginPlay
bPreloadLevelPackagesBeforeOpen
Improvements
Replaced the blocking SearchAllAssets(true) path with a non-blocking asset-registry discovery flow that starts the search once and polls until the registry is ready.
Expanded warmup coverage beyond direct material assets to include worlds, loaded level actors, blueprint-generated classes, class default objects, default subobjects, simple construction script templates, inheritable component handler templates, and primitive components found through referenced objects.
Updated warmup fingerprinting to hash the final discovered asset set and dependency-expansion settings, so instant-skip decisions reflect the actual startup workload instead of just the initial scan input.
Updated warmup completion rules so package preload is part of the startup pipeline, and preload failures block fingerprint persistence the same way asset load failures already do.
Updated the demo boot flow to pass PSOAutopilotWarmupCompleted=1 during travel so the gameplay map can distinguish a boot-flow handoff from a direct launch.
Updated the demo widget to initialize from the subsystem's current state after travel instead of assuming every map load starts a fresh warmup pass.
Fixes
Fixed packaged demo boot flow when LevelToOpenOnComplete is unset by falling back to /Game/Demo/Demo_PSOTorture instead of stalling at the boot map.
Fixed packaged map travel after preload by releasing retained preloaded packages before OpenLevel(...).
Fixed packaged demo content availability by always cooking /Game/DemoMaterials and by updating the demo-generation script to write the gameplay destination instead of None.
Fixed cooked-runtime warmup discovery fallback so packaged builds can still assemble the intended warmup set when registry-backed results are sparse.
Fixed material PSO teardown during garbage collection by removing the plugin-side double release of engine-owned PSO precache request IDs.
Fixed the demo gameplay map starting a second warmup after a successful boot warmup by honoring the boot-flow handoff option in the gameplay manager.
Documentation
Updated Plugins/PSOAutopilot/Docs/README.md to better explain real-project startup coverage, first-run cost shifting, the recommended boot-level flow, and destination-level package preload.
Packaging and Validation
Synced the same source and documentation changes into Plugins/PSOAutopilot, PluginBuild, and PluginStaging.
Build.bat UnrealEditor Win64 Development -Project=PSOAutopilot.uproject -NoUBA succeeded.
BuildPlugin validation passed for UnrealEditor Win64 Development, UnrealGame Win64 Development, and UnrealGame Win64 Shipping.
A live packaged gameplay smoke test passed in Intermediate/PackagedSmokeTest7:
boot warmup discovered 1001 assets
/Game/Demo/Demo_PSOTorture was preloaded during warmup
the retained preload was released before map travel
the gameplay map opened with ?PSOAutopilotWarmupCompleted=1
the gameplay map loaded successfully and skipped the duplicate warmup
Notes
This release moves substantially more startup work into a controlled loading phase, but projects still need to register representative warmup roots for content that is created or selected only at runtime.
Package preloading improves first-run smoothness, but it can increase memory pressure during startup compared with PSO-only warmup.
Added a Startup Setup wizard so first-time users can configure PSO Autopilot from a guided editor tab instead of assembling the startup flow manually.
Added Simple Setup presets that translate approachable choices into the existing advanced startup preparation, content loading, referenced-content, and frame-budget settings.
Added a preflight validator with green/yellow/red setup results and one-click fix actions for common onboarding and packaging problems.
Added the ability to explicitly exclude specific object types (like Blueprints or LevelSequences) from the asset scan, preventing Editor-level crashes during heavy bulk-loads.
Added ClassesToExcludeFromScan to UPSOAutopilotSettings to allow developers to safely bypass problematic asset types during directory scanning.
Child classes of any excluded class are also automatically excluded via dynamic GetDerivedClassNames lookup.
New in This Release
Added a new PSOAutopilotEditor module and registered Window > PSO Autopilot Startup Setup.
Added Simple Setup settings:
SetupMode
SimplePreset
SimpleGameplayLevel
SimpleLoadingWidgetClass
SimpleContentFolders
bSimpleEnableSmartSkip
bSimpleEnableTexturePreheat
Added three Simple Mode presets:
Safe Startup for low-memory, low-hitch startup behavior.
Balanced as the recommended default.
Fast Warmup for smaller projects that can spend more frame time and memory during loading.
Added setup validation for:
game level selection and disk existence,
game level cook coverage,
loading screen validity,
active scan-folder validity,
explicit warmup asset validity,
package preload path validity,
batch-size sanity,
risky ignored content types,
recommended packaged content,
smart cache skip,
loading level selection and package existence,
startup-loader presence in the generated loading level,
project startup level pointing at the loading level,
loading level versus game level mismatch.
Added automatic fix actions:
apply Simple Setup,
use the built-in loading screen,
add /Game as default content to prepare,
remove invalid content and preload entries,
apply the Balanced preset for unreasonable batch size,
clear risky ignored content types from advanced exclusions,
create or open the default loading level,
include recommended content in packaging,
enable smart cache skip,
set the project startup level,
create or update a PSO Autopilot Loader actor.
Added a one-node Blueprint entry point, Start PSO Autopilot Loading Flow, plus FPSOAutopilotSimpleOptions for the recommended gameplay-level warmup, loading widget, package preload, cleanup, and level-travel sequence.
Added friendly loading progress messages and a separate GetTechnicalStatusMessage() telemetry path for advanced/debug loading panels.
Improvements
Simple Setup now feeds the runtime startup-preparation snapshot directly, so the beginner configuration path uses the same production subsystem as Advanced Mode.
Simple Setup now exposes only game level, loading screen, content to prepare, quality preset, smart skip, and texture preparation; low-level tuning remains hidden until Advanced mode is selected.
Presets now ship buyer-ready tuning decisions: Safe Startup, Balanced, and Fast Warmup.
The smart-skip path is now configurable through the Simple Setup toggle or the Advanced bEnableSmartCacheSkip setting.
Added APSOAutopilotBootLoader::ConfigureForSimpleSetup(...) so editor tooling and Blueprint utility code can configure the startup flow without direct property access.
Updated the demo project defaults to use Simple Setup with /Game/Demo/Demo_PSOTorture and /Game/DemoMaterials.
Reframed the bundled sample as a marketplace demo: boot map, loading screen, gameplay map, cold-vs-cached toggle, compact telemetry overlay, and a clear Warmup skipped because cache matched. cache-hit message.
Set the demo project’s default startup map to /Game/Demo/Demo_BootFlow and added the demo maps/content folders to packaging settings.
Updated the README with a 5-minute beginner setup flow focused on the new wizard.
Updated the README and HTML manual with the one-node Blueprint loading-flow path.
Updated the README and HTML manual with packaged-build demo instructions and the 1001-asset packaged smoke-test proof point.
Updated the built-in loading screen so technical details live in an optional telemetry panel instead of the primary player-facing status line.
Renamed user-facing Project Settings, wizard, Blueprint, and built-in loading-screen labels to use buyer-facing startup-preparation language while keeping technical C++ names unchanged.
Improved the Boot Loader Details panel as the main product surface: display name is now PSO Autopilot Loader, the primary setup properties appear first, and overrides/debug/demo controls are grouped behind advanced categories with recommendation-focused tooltips.
Packaging and Validation
Build.bat UnrealEditor Win64 Development -Project=PSOAutopilot.uproject -NoUBA succeeded.
BuildPlugin validation passed for UnrealEditor Win64 Development, UnrealGame Win64 Development, and UnrealGame Win64 Shipping.
Notes
The wizard now uses a hidden default loading level for startup-flow generation, can create/open that level, and points the project startup level at it before creating or updating the startup-loader actor.
The wizard validates setup and compiles successfully, but the UI was not manually clicked through in an interactive editor session during this pass.
Fixed a packaging time regression caused by the Setup Wizard. The wizard no longer recommends adding the entire /Game folder to DirectoriesToAlwaysCook, which previously disabled the engine's reference-based cook optimization and forced cooking of all unreferenced assets.
Added a new HasRootCookDirectory validation check to the Setup Wizard. It now detects if /Game is included in the project's Cook Directories and provides a one-click Remove /Game auto-repair action.
Fixed repeat startup warmups after an Unreal restart by making smart-cache hits skip the asset warmup even when the engine reports a pipeline-cache backlog during fresh process startup.
Fixed stale setup-loader debug flags carrying forward when an existing loader is updated by the wizard. Re-running setup now clears Ignore Previous Runs and demo hold overrides so the loader does not reset the smart-skip fingerprint on every startup.
Smart-cache hits now bypass demo minimum-duration holds, so a matched repeat run completes immediately instead of looking like another warmup.
Fixed the setup wizard's loading screen path so it creates and selects an editable Widget Blueprint at /Game/PSOAutopilot/WBP_PSOAutopilotLoadingScreen instead of silently pointing new startup flows at the native C++ fallback widget.
Added an Editor Iteration Mode setting, defaulting to Use Unreal Editor Compilation, so PIE/editor preview uses Unreal's standard shader compilation path unless the user explicitly switches to Run PSO Autopilot Warmup.
Fixed a use case that occurs when loading a massive amount of complex materials concurrently.
Implemented a background task throttle in the time-sliced batch processing loop. The plugin now caps active PSO precache requests to 250 in-flight tasks and yields the frame, preventing the renderer's uniform buffers from being overwhelmed by unchecked background threads.
Manual (https://gregorigin.com/PSO_Autopilot/) and FAQ (https://gregorigin.com/PSO_Autopilot_FAQ/) are expanded and extended.
Added bAutoOpenLevel (Auto Open Level) to PSOAutopilotBootLoader and PSOAutopilotCinematicBootLoader. When disabled, the loader fires the “On Startup Preparation Finished” event but delegates the actual level transition to the user’s Blueprint logic, making it easier to integrate with third-party async loading screen plugins without triggering unwanted double loading screens.
True Autopilot (Adaptive Frame Pacing): The plugin now acts as a dynamic governor. It monitors real-time Game Thread and Render Thread execution times, automatically expanding the PSO budget on high-end hardware (like an RTX 4090) and aggressively throttling it down on constrained hardware (like a Steam Deck) to guarantee a buttery-smooth loading screen.
AAA Cinematic Handoff: Seamlessly hide compilation behind unskippable studio logos or intro cinematics (.mp4 files) using the new CinematicBootLoader. It orchestrates perfect timing handoffs, enabling a “Press Any Key to Skip” prompt if compilation finishes early, or crossfading to a fallback UI spinner if compilation outlasts the video.
Spatial / World Partition Warmup: Eliminate traversal stutter in open-world games. The new PSOAutopilotSpatialComponent attaches to the Player Pawn, scans the environment using an async radius sweep, and queues upcoming actors for JIT warmup before the player reaches them.
Just-In-Time (JIT) Micro-Warmups: Need to spawn a massive boss mid-game without freezing? The new Blueprint node Warmup Actor Class (Time-Sliced) allows surgical, non-blocking shader compilation during active gameplay.
“Bloat Finder” Profiler Dashboard: An Editor-only tool that tracks the exact number of PSOs generated by each asset during validation runs. Available under Window > Tools > PSO Autopilot Bloat Profiler, it presents a dashboard of the “Top 10 Heaviest Assets” so you can instantly identify and optimize your worst offenders.
Important Notes
Smart Cache Skip & Startup Time: When Smart Cache Skip is enabled, a repeat startup may still take a couple of seconds before transitioning. This is not a bug; it is the time required for Unreal Engine to asynchronously load the Asset Registry (needed to verify the cache fingerprint) and to asynchronously preload the gameplay map (which prevents a synchronous hard freeze when OpenLevel is called).
Bug Fixes
Fixed an issue where clearing the “Content Folders” (or DirectoriesToScan) array in the settings would cause it to default back to /Game on the next engine startup. Empty arrays are now correctly preserved.
Fixed a Setup Wizard validation error that incorrectly flagged a missing content folder if the user intentionally left the directories blank to rely entirely on specific explicitly configured assets.
Documentation
Documented the composition-over-inheritance path for custom loading widgets in Plugins/PSOAutopilot/Docs/README.md and Plugins/PSOAutopilot/Docs/faq.html. Custom loading widgets do not need to inherit from the plugin’s UPSOAutopilotLoadingScreenWidget — a plain UserWidget Blueprint that composes the subsystem’s delegates avoids the well-known C++/BP issue where the parent class’s UPROPERTY constructor defaults clobber a child Widget Blueprint’s element values on construction.
Added a new FAQ entry (“Can I use a fully custom UMG widget without inheriting from UPSOAutopilotLoadingScreenWidget?”) covering both the one-node Start PSO Autopilot Loading Flow path and the manual sequencing path (Create Widget → Add to Viewport → StartWarmup → release retained preload + Open Level), with a list of useful BlueprintPure getters for driving richer UIs.
Added a Troubleshooting FAQ entry explaining why custom Widget Blueprint elements reset to the C++ defaults when reparented to UPSOAutopilotLoadingScreenWidget, and how to fix it by reparenting to plain UserWidget.
Expanded the “Custom UI Integration” section of the plugin manual to make the composition path the recommended approach.
Developer Tools
Added Scripts/CreateSampleBPLoadingWidget.py, an editor Python script that generates a sample BP-only loading widget scaffold at /Game/PSOAutopilot/WBP_PSOAutopilotSampleLoadingScreen.uasset, parented to plain UserWidget, then compiles and saves the asset. Verified to run cleanly in headless UnrealEditor-Cmd.exe -ExecutePythonScript mode and from the in-editor Tools → Execute Python Script… menu.
Added Scripts/SampleBPLoadingWidget_README.md, a comprehensive illustrated walkthrough covering: why composition beats inheritance (with ASCII inheritance diagrams), a rendered visual mockup of the loading screen at runtime, a six-step Designer-tab build guide (Background → CenterBox → Title_Text → Status_Text → Progress_Bar → Percent_Text) with per-step property tables for Slot / Appearance / Content / Behavior fields, a three-event Graph wiring walkthrough (Event Construct + HandleProgress(float, string) + HandleComplete), two boot-flow integration options (one-node helper vs. manual sequencing), a customize-without-breaking-bindings reference, a Troubleshooting section, and an API cheat sheet of the subsystem’s delegates, lifecycle calls, getters, and helper-node options struct.
Documented in both the script and the README that UE 5.7’s stock Python bindings cannot author UMG widget trees (UWidgetBlueprint.WidgetTree and UBlueprint.GeneratedClass are protected UPROPERTYs without script-access metadata). The script therefore handles everything Python can automate (asset creation, parent class, compile, save) and the README’s illustrated walkthrough covers the manual Designer-tab build (~5 minutes) and Graph wiring (~1 minute).
Setup Wizard version banner. The wizard’s logo header now displays the installed plugin version (e.g. PSO Autopilot v1.2.1), pulled live from the plugin descriptor’s VersionName.
Editable Loading Level in Simple Setup.SimpleLoadingLevel is now exposed in the Simple Setup property panel as a standard world-asset picker (previously UPROPERTY(Config) only, with no UI). Users can point Simple Setup at an existing level they already built instead of being forced through the wizard’s Create/Open fix.
Confirm-button flow on APSOAutopilotBootLoader. When Auto Open Level is off, the loading widget is now left in the viewport so a Blueprint can drive a “Click to Continue” / confirm-button pattern. Remove Loading Widget When Ready is ignored in this mode; the Blueprint owns the rest of the flow.
New BP function Dismiss Loading Widget on APSOAutopilotBootLoader. Call from a custom flow (e.g. after the confirm-button click) to tear down the loading widget without relying on a level transition to clear it.
Bug Fixes
Black screen on the second run with bAutoOpenLevel=false. In packaged builds with a custom confirm-button flow, the loader previously removed the loading widget the moment warmup completed regardless of Auto Open Level. On the second run (smart-cache-skip path) warmup completed essentially the same frame the widget was added, producing a black screen with no way back. The widget is now retained whenever Auto Open Level is off.
Confirm button disappeared in packaged builds. Same root cause as the black screen; the widget was being yanked out from under the player at warmup-complete. The new gating fixes both editor and packaged behavior consistently.
Documentation
Added a clear explanation of Unreal’s /Game/ path prefix (= the project’s Content/ folder, not a literal folder).
New FAQ entries in Docs/FAQ.html.
Updated FAQ entries:“What should I choose in Simple Setup?” now leads with the new Loading Level item; “What does the Boot Loader actor do?” lists Dismiss Loading Widget; “The loading widget asset path looks wrong” explains why a fresh install warns about a path that doesn’t exist yet.
Manual (Docs/Manual.html): Quick Start lists the new Loading Level picker; Boot Loader properties table rewritten for Auto Open Level semantics and adds rows for Remove Loading Widget When Ready and Dismiss Loading Widget; new callout “Confirm-Button Flow Pattern (1.2.1)”.
README (Docs/README.md): Beginner setup checklist now leads with Loading Level; /Game/ prefix explained in a blockquote; new subsection Confirm-Button Flow (1.2.1).
Explicit pipeline-cache PSO counters for Blueprint/UI. Added three clear subsystem getters for the engine pipeline-cache flush stage: Get Pipeline Cache Total PSOs, Get Pipeline Cache Compiled PSOs, and Get Pipeline Cache Remaining PSOs. This makes it possible to show /allshaders-style progress without scraping status strings.
Phase-aware progress summary text. Added Get Current Progress Summary Text, which automatically switches between asset counts, gameplay-package preload counts, pipeline-cache PSO counts, demo-hold timing, and cached-run states. The native loading widget and bundled boot loader now surface that summary directly instead of leaving users to infer state from raw percentages alone.
Sample/demo telemetry updated for real packaged validation. The built-in demo telemetry now prints the new pipeline-cache counters, and the BP-only sample-loading-widget scaffold/readme now uses the phase-aware progress summary path so the on-screen label tracks the actual warmup phase cleanly.
Min PSO Queue To Wait surfaced in Simple Setup. The final pipeline-cache backlog threshold is now available in Simple Setup as an optional advanced foldout while staying synced with the underlying Advanced-mode setting. Teams can force the 0.95 -> 1.00 hold to appear for smaller backlogs without switching setup modes.
Bug Fixes
Pipeline-flush tracking now resets cleanly on cancel/stop paths. This prevents stale flush counters or leftover state from leaking into the next validation run.
Ambiguous runtime counters were clarified.Get Remaining Graphics Tasks is now documented as the current batch PSO-precache backlog, not the engine’s full pipeline-cache total, reducing misread telemetry during packaged tests.
Documentation
Packaged-build testing guidance was expanded substantially. The FAQ now documents the recommended cold-run / preload / pipeline-flush / cached-run test sequence, including -log -clearPSODriverCache, Smart Skip reset guidance, and minimum-hold recommendations for short runs.
Packaged-build symptom explanations were added. The FAQ now explicitly explains why users may see 0 or 1 processed items, why the bar can jump straight to 85%, why the gameplay level can open immediately after that, and how to distinguish asset warmup, gameplay-package preload, pipeline-cache flush, and cached-run states using Get Current Progress Summary Text.
PIE-vs-packaged asset discovery differences are now documented. Added FAQ guidance explaining that PIE can enumerate uncooked editor content while packaged builds only see cooked staged runtime content, so matching processed counts are not guaranteed even when setup looks correct in editor.
Cook-list vs processed-count confusion was addressed. The FAQ now calls out that seeing folders under Additional Asset Directories to Cook is only partial confirmation, and that adding dozens of folders to Packaging does not imply the loading screen should show the same number of processed items.
Recursive folder scanning is now explicit in the FAQ. Added a dedicated entry confirming that Content to Prepare / Directories To Scan recurse through subfolders automatically (for example, /Game/SomeFolder includes /Materials, /Meshes, and deeper children), and clarifying that this is separate from dependency expansion outside the selected folder tree.
README and sample-widget docs were refreshed. The manual/readme now mention the Simple Setup advanced foldout for Min PSO Queue To Wait, and the Blueprint sample-widget walkthrough was updated to use the new phase-aware summary getter.
New explicit loading-screen update interface. Added PSOAutopilotLoadingScreenReceiver so any UUserWidget can receive loading progress, summary text, technical status, and telemetry visibility updates without inheriting from the native fallback widget.
New editable loading-screen base class. Added UPSOAutopilotEditableLoadingScreenWidget, a project-friendly UMG parent that only updates optional named bindings such as WarmupProgressBar, WarmupStatusText, WarmupProgressSummaryText, WarmupTimerText, SpinnerImage, and optional telemetry widgets.
Wizard-created loading widget templates. Simple Setup / Create-Update Startup Flow now creates real project-owned Widget Blueprint templates at:
Interface-driven auto-updates in built-in flows.Start PSO Autopilot Loading Flow and APSOAutopilotBootLoader now auto-drive any widget that implements PSOAutopilotLoadingScreenReceiver, instead of requiring a cast to UPSOAutopilotLoadingScreenWidget.
Bug Fixes
Wizard widgets no longer feel hard coded. The old behavior where missing bind widgets triggered runtime layout regeneration has been split away from the editable path. Wizard-created widgets are now safe to customize directly in the Designer without fighting a procedural rebuild.
Native fallback is now truly fallback-only.UPSOAutopilotLoadingScreenWidget now procedurally builds its stock dark-mode layout only when the exact native class is used. Project Widget Blueprints no longer get runtime UI injected into their designer tree.
Setup Wizard now repairs stale native loading-widget assignments. If Simple Setup or an existing loader points at a native PSO Autopilot widget class instead of a project-owned asset, the wizard regenerates the editable widget templates and reassigns the standard template automatically.
Editable-widget helper script now follows the new parent path.Scripts/CreateEditableLoadingWidget.py now creates widgets parented to UPSOAutopilotEditableLoadingScreenWidget, matching the runtime/editor behavior and avoiding the old fallback-layout confusion.
Packaged Smart Cache Skip no longer stores warmup fingerprints in GameUserSettings.ini, which Unreal could invalidate and wipe on the next boot.
Warmup fingerprints now persist in Saved/PSOAutopilotCache.ini, so cached packaged launches can reliably skip the startup warmup sequence.
Legacy Smart Cache entries are still detected and migrated forward, then cleaned up after a successful read/write cycle.
Documentation
README updated for the new editable-widget path.Docs/README.md now describes the wizard-created template widgets as the default editable route, explains the new UPSOAutopilotEditableLoadingScreenWidget parent, and documents the interface-based custom-widget path.
FAQ updated to match the product.Docs/faq.html now explains that:
the wizard creates editable template widgets instead of empty children of the native fallback widget,
UPSOAutopilotLoadingScreenWidget is now the convenience fallback only,
fully custom widgets can implement PSOAutopilotLoadingScreenReceiver or bind delegates manually,
current wizard widgets avoid the old parent-default propagation pitfall by using UPSOAutopilotEditableLoadingScreenWidget.
HTML manual refreshed.Docs/index.html now reflects the new loading-widget template assets, the fallback-vs-editable split, and the interface-based update path for the Boot Loader and one-node flow.
Testing guide updated.Docs/TESTING.md now distinguishes between:
the exact native fallback widget,
the editable wizard templates,
and fully custom composition/interface-driven widgets.
Sample/scaffold docs clarified.Scripts/CreateSampleBPLoadingWidget.py and Scripts/SampleBPLoadingWidget_README.md now explain the new split between the native fallback widget, the editable template widget base, and the fully BP-only composition sample.
Validation
A cold packaged Development run saved the warmup fingerprint successfully.
The immediate second packaged run matched the saved fingerprint and skipped the asset warmup path as intended.
Setup Wizard now previews Content to Prepare coverage. The validator shows how many warmable assets the current setup resolves before packaging, including worlds, Blueprints, widgets, static meshes, skeletal meshes, materials, VFX, and other assets.
Material-heavy warmup selections are flagged. If Content to Prepare is mostly material folders with almost no maps, meshes, Blueprints, widgets, or VFX, the validator warns that PSO coverage may be limited and recommends adding the runtime assets that use those materials.
Destination level wording is clearer. Simple Setup, the Boot Loader, and the Blueprint loading-flow node now label the destination as Level To Open After Warmup, with matching Warm Level To Open Before Opening and Preload Level To Open Package labels.
Allow Custom Startup Level now stays visible as a risk. Enabling it no longer produces a healthy-looking validator row; the wizard warns that content shown before the PSO loading level is outside PSO Autopilot’s protection.
Configuration tooltips now explain warmup targeting. Content-folder, explicit-content, referenced-content, and boot-loader helper fields now describe the intended maps, Blueprints, meshes, widgets, VFX, Primary Asset Labels, and material usage instead of leaving users to infer that material folders are sufficient.
Startup-flow drift is now treated as a blocking setup issue. The Setup Wizard now checks whether the placed PSO Autopilot Loader still matches the current Simple Setup destination and handoff options, and flags mismatches before packaging.
Destination-map failures stay visible on the loading UI. If the Level To Open After Warmup is missing from the packaged loader, the loading widget remains visible and receives a clear terminal error instead of fading away.
Bug Fixes
Simple Setup edits now persist immediately. Project settings changes are saved when edited, reducing cases where the editor UI looked correct but packaged runtime settings still used older values.
Simple-mode snapshots no longer inherit stale Advanced roots. Applying or capturing Simple Setup now resets hidden advanced explicit warmup and preload arrays before adding the current Simple destination seed/preload entries.
Stale loader actors are now detected. Existing loading levels with a loader actor that still opens an old map now report an error and offer Create/Update Startup Flow instead of passing validation just because any loader exists.
Startup map mismatch is now an error when custom startup is not allowed. If Allow Custom Startup Level is off, the validator now treats a project startup map that is not the PSO loading level as a blocking error.
Set Startup Level now also updates the editor startup map. The wizard writes both GameDefaultMap and EditorStartupMap to the selected loading level.
Boot loader validates the destination before removing the widget.APSOAutopilotBootLoader now checks FPackageName::DoesPackageExist(...) first; missing cooked maps leave the loading widget up with an actionable message.
Blueprint loading-flow node gets the same destination guard.Start PSO Autopilot Loading Flow now keeps the widget visible and logs a clear error when the destination package is missing.
Package preload failures are explicit. Before LoadPackageAsync, PSO Autopilot now checks whether the requested package exists and logs an error pointing to Packaging Maps to Cook / Additional Asset Directories to Cook when it is missing.
Packaged warmup discovery diagnostics are now explicit.LogPSOAutopilot now prints the effective runtime warmup settings at StartWarmup(), including scan directory count, explicit warmup roots, queued runtime roots, preload packages, dependency-expansion state, pipeline-cache wait settings, and Smart Skip state. This makes it clear whether packaged builds actually received the setup settings users configured in the editor.
Low-coverage warmups now warn instead of looking healthy. Asset discovery now logs a breakdown of directory-discovered assets, configured explicit assets, runtime seed assets, seed packages, expanded dependency packages, and dependency assets. If the run only discovers the queued runtime root asset(s), the log warns that PSO coverage is limited and points users toward content folders, explicit startup assets, or cooked AssetRegistry dependency data.
Dependency expansion gaps are easier to identify. When dependency expansion is enabled but no dependency packages are found for the configured warmup seeds, PSO Autopilot now emits a targeted warning instead of silently continuing with a tiny warmup set.
Pipeline-cache wait decisions are logged. Warmup completion now logs when the final engine pipeline-cache flush is skipped because the remaining PSO count is under the configured threshold, and also logs the remaining count when the pipeline-cache wait is disabled.
Sparse packaged scans now include examples in warnings. Low-coverage and dependency-expansion warnings include sample scan folders and discovered assets so support can quickly tell whether the packaged build saw the configured folders or only the destination seed.
Documentation
Menu-first startup setups are clarified in the FAQ.Docs/faq.html now explains that Level To Open After Warmup is the destination concept, and that the destination can be a main menu, hub, or gameplay map.
Main-menu handoff guidance was added. Added a FAQ entry explaining the intended flow for games that must land in a main menu before gameplay: PSO_Level -> MainmenuLevel, with gameplay/menu assets warmed through Content to Prepare, explicit warmup assets, Primary Asset Labels, or RegisterRuntimeWarmupAsset(...).
Pre-PSO startup maps are called out. The FAQ now warns that language picker, account, splash, or other custom startup maps that run before the PSO loading level can still hitch before PSO Autopilot has a chance to run, and recommends keeping them lightweight or folding that UI into the PSO loading level.
Allow Custom Startup Level is now documented directly. Added a FAQ entry explaining that this checkbox only suppresses the startup-map validation warning; it does not make the custom startup map run PSO Autopilot or warm content that appears before the PSO loading level.
Content to Prepare guidance was expanded. Added FAQ entries explaining what belongs in Content to Prepare, why material-only folders are not enough, why many folder entries can still produce only one startup asset, and how the new validator/log diagnostics expose that condition.
Crash triage guidance was added. Added a troubleshooting entry explaining that Session CrashGUID alone is not evidence of a crash and that real crash reports need fatal markers, call stacks, or CrashReportClient activity.
Online / offline HTML manual was expanded with illustrated update guidance.Docs/index.html now includes a visual feature-update section, startup-flow diagrams, Content to Prepare coverage cards, validator preview examples, packaged-log examples, and matching manual troubleshooting entries.