New editable sample widgets + BP for those interested:
CreateEditableLoadingWidget.py (5.6 KB)
LoadingWidgetTemplates_README.md (2.4 KB)
New editable sample widgets + BP for those interested:
CreateEditableLoadingWidget.py (5.6 KB)
LoadingWidgetTemplates_README.md (2.4 KB)
1.3.1a, 2026-06-04
Bug Fixes
β’ Fixed Infinite Loading Screen: Resolved an emergent deadlock issue where the loading screen would hang indefinitely at βFinding startup assetsβ¦β when launching in Standalone Game mode. The plugin now correctly binds and listens to the Asset Registry OnFilesLoaded delegate without prematurely yielding the tick.
β’ UE 5.7 Compilation Fix: Fixed an βincomplete typeβ / βunrelated pointersβ compilation error in PSOAutopilotSubsystemHelpers.cpp on Unreal Engine 5.7 by adding the explicit include βUObject/Package.hβ dependency for GetTransientPackage() during NewObject construction.
FPSOAutopilotPlatformOverride) lets you replace the effective items-per-step, frame-time budget, memory-cleanup, and pipeline-cache wait on a named platform (Windows, Mac, Linux, Android, IOS). An enabled override matching the running platform is overlaid onto the runtime snapshot; disabled or non-matching entries are ignored.PSOAutopilotCoverage commandlet resolves the configured warmup content via the asset registry, prints a per-type coverage report, and returns a non-zero exit code when discovered assets fall below -MinAssets=<N>, so a content/cook regression fails the build. Run: UnrealEditor-Cmd.exe <project> -run=PSOAutopilotCoverage -MinAssets=50. Its dedup/counting/threshold accounting is extracted into FPSOAutopilotCoverageReport and unit-tested.Scripts/Run-CI.ps1 chains build β PSOAutopilot.* automation tests β coverage gate and fails fast on the first failed stage, for local pre-flight or a CI runner. The coverage floor defaults to -MinAssets 900, so losing the demo content set fails the gate.ApplySimplePresetTuning) applied identically to the persistent settings object and the runtime snapshot, so the two can never drift.CaptureFrom and ApplyTo now share one field list (PSO_SNAPSHOT_COPYABLE_FIELDS X-macro), so adding or removing a snapshot-copied setting cannot desync capture and restore.CaptureEffectiveFrom layers the Simple-mode seed and the per-platform override over the raw capture; Advanced mode passes raw content through unchanged.FPSOAutopilotSettingsSnapshot::Sanitize() trims, de-duplicates, and clamps the snapshot before warmup consumes it (wired into the live warmup start path alongside CaptureEffectiveFrom).FPSOPipelineFlushTracker.Automation RunTests PSOAutopilot, NullRHI), exit code 0: SettingsPresetTuningParity, SettingsSnapshotRoundTrip, SettingsEffectiveCapture, SettingsSanitize, SettingsPlatformOverride, PipelineFlushTracker, SettingsSimpleSetupMerge, LiveSmokeTest, CoverageReport, CoverageFolders.-MinAssets=0 β βCoverage gate passed (1001 >= required 0)β, exit 0; -MinAssets=5000 β βCoverage gate FAILED β¦ below β¦ 5000β, exit 1.Scripts/Run-CI.ps1 runs build + tests + coverage green end-to-end (exit 0).PS1 files are not allowed in Fab packages. I provide them here for those interested in up-to-date validation and integration scripts:
Run-CI.ps1 (9.8 KB)
ShippingValidation_README.md (1.8 KB)
Build-ShippingValidation.ps1 (11.8 KB)
This plugin seems amazing! Weβd love to buy it for our project, but we need it to be compatible with UE5.8. version.
This technical update adds per-platform tuning, headless coverage/CI tooling, and a phase-aware
pipeline-flush ETA. Finally it hardens the internals with a full decomposition of the warmup engine.
The monolithic warmup subsystem (2,700+ lines) was decomposed into a thin coordinator plus
eight focused, individually unit-tested collaborators. Runtime behavior, the Blueprint API,
and the C++ public API are unchanged.
UPSOAutopilotSubsystem (coordinator: state machine + Tick)
β
βββββββββββββ¬ββββββββββββ¬ββββ΄βββββββββ¬ββββββββββββββ¬ββββββββββββββ
βΌ βΌ βΌ βΌ βΌ βΌ
Progress Fingerprint Warmup Package Batch JIT
Reporter Store Discovery Preload Mgr Loader Warmup Mgr
β β β β β β
βββββββββββββ΄ββββββββββββ΄ββββββ¬βββββββ΄ββββββββββββββ΄ββββββββββββββ
βΌ
AssetWarmupEngine + TextureStreamingStep
(shared per-asset PSO precache & texture work)
Source/PSOAutopilot/{Public,Private}/Warmup/: FPSOWarmupProgressReporter (progress bands, summary text, ETA inputs), FPSOWarmupFingerprintStore (smart-cache skip persistence), FPSOWarmupDiscovery (asset scanning + runtime-asset queueing), FPSOPackagePreloadManager (gameplay-map preloads), FPSOAssetWarmupEngine (per-asset PSO precache work), FPSOBatchLoader (time-sliced batch loop), FPSOJitWarmupManager (just-in-time actor-class warmup), FPSOTextureStreamingStep (texture residency phase). The pipeline-flush accounting extracted earlier (FPSOPipelineFlushTracker) completes the set.ResetWorkAndCompileEvents, AbandonInFlightWork, ReleaseEngineRequests, ClearStagedNames), each a 1:1 wrap of the previous inline call sites. Dead code removed (MergeRuntimeAndFilter, QueueByPath).EPSOWarmupState moved to its own thin header Public/PSOAutopilotWarmupState.h. PSOAutopilotSubsystem.h still includes it, so existing C++ user code compiles unchanged; the Blueprint enum path is identical..ini (new test-only config-path seam), so running the suite no longer clears the developerβs real smart-cache history.Scripts/Run-PackagedWarmupSmoke.ps1): cooks a Win64 build, launches it, and asserts the warmup state machine reaches Finished (Success=true) without hanging; catching the class of regression that headless NullRHI tests cannot see. The script clears the smart-cache fingerprint itself so a cached skip can never produce a vacuous pass.Scripts/Run-CI.ps1 reliability fix: stage waits use WaitForExit() instead of Start-Process -Wait, which could hang indefinitely on a lingering editor child process.Warmup Finished. Success=true, no livelock.BuildPlugin builds succeeded on UE 5.5, 5.6, and 5.7 with the decomposed module layout.UE5.8 update in this case is a challenge, but I want to do it sooner rather than later. ![]()
/Content (fixes potential sample asset issues on UE 5.5). Nothing depended on it: every path in the runtime module, the editor module, and the documentation resolves /Game/..., never the /PSOAutopilot/... mount point. The loading screen is created in your project by the setup wizard, and the demo is generated by Scripts/CreatePSOAutopilotDemo.py; both of which save through your editor, so the assets always match your engine version. This removes thePlugins/PSOAutopilot/Content/ folder β and its warnings, if present β can survive the upgrade. Delete that folder once; nothing references it.Public/Warmup/*.h headers used FSoftObjectPath, TSubclassOf,TObjectPtr, and TWeakObjectPtr while including only CoreMinimal.h, which no longerStopWarmup β which is BlueprintCallable and the Cancel path on the loading-flowUpdateResource() tearsSetForceMipLevelsToBeResident per duplicate; in a single frame, at the exact moment the loadingPSOAutopilot.WarmupMaterialDedup test that pins the de-duplicationReset.The setup wizard generates the demo for your specific setup, no more manual stuff.
Generate Demo Content. Window > PSO Autopilot Startup Setup now has a button that creates the
demo in your project: the boot flow, the stress level, 1000 material instances, the loader and the
loading screen. It is offered whether or not the demo already exists β labelled Regenerate Demo
Content when it does β because the generator is idempotent and anyone clearing a stale
Content/ folder after upgrading from 1.3.5 needs exactly this.
Before this, generating the demo required knowing that an experimental, disabled-by-default
engine plugin had to be enabled, and then building it. The plugin has shipped no bundled demo content since 1.3.6, by design.
The wizard tells you when Python is missing. Generate Demo Content needs the Python Editor
Script Plugin, which Unreal disables by default. If it is off, the wizard now names the menu path
instead of idling.
The setup wizardβs validation logic no longer lives inside the widget.
SPSOAutopilotSetupWizard.cpp drops from 1,973 to 878 lines. All 13 validation rules, their
supporting helpers and the discovery-preview scan move into FPSOAutopilotSetupValidator, which
has no Slate dependency and reaches the editor only through a small probe interface.
This is why the editor module had no tests for its entire life: the logic was private to a Slate
widget and unreachable. Runtime behaviour, the wizardβs appearance and every message string are
unchanged β rule bodies were moved verbatim.
inline/constexpr before the split. Two .cpp files in one module defining the samePSOAUTOPILOT_API andPrivate/, so a C++ caller received aPublic/; no API changed.PSOAutopilot.LoadingFlowActionLifecycle pins the async nodeβs contract: the factory returns aActivate(), and cancellingPSOAutopilot.StatusSnapshotParity asserts every status field equals the getter it mirrors, soRemoved a deprecated engine call that would have broken future builds.
ForEachObjectWithOuter was being passed a boolean bIncludeNestedObjects; UE 5.8 deprecates
that form in favour of an EGetObjectsFlags enum and warns that it will stop compiling in a
later release:
warning C4996: 'ForEachObjectWithOuter' with a boolean bIncludeNestedObjects has been deprecated
- please use the EGetObjectsFlags enum instead - Please update your code to the new API before
upgrading to the next release, otherwise your project will no longer compile.
Because true is the default on 5.5β5.7 and IncludeNestedObjects is the default on 5.8, the
argument was simply dropped β identical behaviour on every supported engine, and no
version-specific code.
Who this affected: the plugin ships as source, so on 5.8 this was a compiler warning. Editor work and PIE were unaffected.
BuildPlugin against every supported engine as aVersionName and Version encode each other (1.4.0 β 140).PSOAutopilot.EditorPreviewWidgetFlags pins the nested-object traversal inBuildPlugin β editor and packaged-game targets β against UE 5.5, 5.6, 5.7Scripts/CreatePSOAutopilotDemo.py produced the full setPSO Autopilot Warmup Finished. Success=true on content that engine generated itself βFingerprintMatched=false, so the smart-cache skip did not short-circuit the asset loop.UnrealGame Shipping target on all four engines, and a packaged Shipping build completesWITH_EDITOR isUE_BUILD_SHIPPING is set, and optimisation differs β so a Development-only smoke does