0.5.0 update, 2026-09-28 
Supports Unreal Engine 5.5, 5.6, 5.7 and 5.8 from one source tree, with 5.5 as the floor.
Lighting policy: Lumen, hardware ray tracing, MegaLights and the GI method 
TargetFrame can now manage how a scene is lit, as one more rung on the adaptation ladder. Off by
default in Advanced Mode (bEnableLightingPolicy); Simple Mode enables it together with its other
project-specific rendering overrides.
- Six modes, cheapest to richest:
Static, ScreenSpace, LumenSoftware, LumenHardware,
LumenHardwareMegaLights, plus ProjectDefault (leave the project’s setup alone). Each maps to
r.DynamicGlobalIlluminationMethod, r.ReflectionMethod, r.Lumen.HardwareRayTracing and
r.MegaLights.Allowed.
- Never above the project. The project’s own setup (read at startup from its renderer settings)
is the ceiling for every tier and for the player’s choice. A project without MegaLights never gets
it; a project on screen-space GI is never raised to Lumen.
- Only rungs that exist. Hardware ray tracing and MegaLights are offered only where the
hardware-RT guard allows them; Static only when the world has built lighting (configurable);
MegaLights only when the project enables it (r.MegaLights.EnableForProject).
- Per tier: Performance
LumenHardwareMegaLights, Mainstream LumenSoftware, Entry
ScreenSpace by default. At runtime the governor steps lighting down after culling and before
overall quality, never below MinimumRuntimeLighting, and restores it in reverse order.
- Screen-space fallback. When scalability scales Lumen off (GI quality 1 on UE 5.5 to 5.7), the
scene would otherwise lose global illumination entirely; TargetFrame switches to screen-space GI
instead (bFallBackToScreenSpaceWhenLumenIsScaledOff).
- Reported in
FTargetFrameStatus::Lighting, the setup notes, the preview, the capabilities scan,
the CSV (LightingMode) and DescribeRuntimeState; captured and restored with every snapshot.
Player graphics settings: API and a ready-made screen 
GetPlayerSettings / ApplyPlayerSettings: quality, 3D resolution, frame-rate goal
(0 = automatic), frame-rate cap, V-Sync, display mode, resolution, lighting, adaptive on/off.
GetPlayerSettings returns the player’s choice, never the governor’s current reductions.
ApplyPlayerSettings saves the choice, makes it the new ceiling, and resumes the governor from it.
GetRecommendedPlayerSettings returns a setup for this machine with its reasons, worded for
players (“This graphics card scores 231 on the engine’s performance index; Performance starts at
115.”).
GetAutomaticTargetFPS is what “Automatic” resolves to on this machine (tier, handheld and
battery rules), for labelling the option.
UTargetFrameSettingsWidget: a complete, gamepad- and keyboard-navigable graphics screen in
C++ Slate, with a “Recommended for this PC” button, revert, apply and a live frame-rate readout.
UTargetFrameSettingsWidget::ShowGraphicsSettings(PlayerController) opens it; the experience
widget gains a “Graphics settings…” button, on its own line under the quick choices, that
does the same.
SetUserSettingsOverride points TargetFrame at a settings object other than
GEngine->GetGameUserSettings().
Fixes 
Each was reproduced by a test that failed on the unfixed code before the fix was written.
- Renderer console variables were written below the priority the project sets them at.
URendererSettings applies the GI method, reflection method, Lumen hardware RT, anti-aliasing
method and TSR upsampling at project-setting priority, which outranks the game-setting priority
TargetFrame wrote at, so those writes were silently dropped. In 0.4.0 this meant the hardware
ray-tracing guard could never actually clamp (invisible on machines that allow HWRT) and upscaler
anti-aliasing writes did nothing. TargetFrame now writes at project-setting priority when, and only
when, the variable is already there. Tests: HardwareRayTracingGuardCanClamp,
LightingPolicyAppliesAndRestores.
- Session-only changes were saved to disk.
UGameUserSettings::ApplySettings always calls
SaveSettings (verified in the 5.5 and 5.8 sources). TargetFrame called it at five sites that are
meant to be session-only (cinematic mode, snapshot restore, benchmark apply, SaveCurrentSettings
and dirty-settings flush), so with bPersistAutomaticChanges off, governor reductions, clamps and
cinematic raises were still written to the player’s config. They now apply with
ApplyNonResolutionSettings inside a render-state recreate context: nothing saved, no window
re-apply. Test: SessionOnlyChangesAreNotSaved.
- A preset at a non-default resolution was treated as a custom mix. The engine reports an overall
level only when resolution quality equals the preset’s default, so “High at 100%” read as custom:
the overall-quality lever was disabled and the player’s quality ceiling skipped, which let
cinematic mode raise High to Epic. Presets are now recognised regardless of resolution, and the
ceiling is the baseline’s minimum per-group level. Tests: PresetWithOwnResolutionIsNotACustomMix,
PlayerApplyBecomesTheNewCeiling.
- A stale baseline survived deactivation.
ResetToDefaults and baseline restore released control
but kept the old baseline, and the next activation reused it. The baseline is now marked stale and
recaptured on the next activation.
- The test harness itself resized the window and saved. Tests called
ApplySettings(false),
which re-applied the player’s saved 2560x1440 to the 1280x720 test window and saved to disk, so the
soak ran at 1440p after the Runtime suite. Found through a new SOAK env log line; all tests now use
ApplyNonResolutionSettings.
- The resolution lever never moved for a player who had not saved a scale. Every supported engine
gives a fresh profile ResolutionQuality 0, meaning “the project’s default screen percentage”
(FQualityLevels::SetDefaults). TargetFrame read it as 0%: the status and the experience panel told
players “3D scene at 0.0% scale” and “quality level -1”, and the player’s resolution ceiling became
0, so every resolution step was clamped to nothing and the governor skipped that lever. The project
default now resolves to what the engine renders at (its own screen-percentage heuristic for the game
viewport); the lever steps down from it and back up to it, writing the default itself back rather
than a fixed number, and applying the settings screen without touching the scale keeps it.
Status.bResolutionScaleIsProjectDefault says which it is. Found while filming the tutorial: the
soak tests pin the scale to 100% before they start, so none had ever run from a fresh profile.
Test: ProjectDefaultResolutionIsAScale (red: dev-tests-58-defres-red.log).
Behaviour changes to check when upgrading 
- A
UGameUserSettings subclass that hooks ApplySettings no longer sees TargetFrame’s session
applies. Hook ApplyNonResolutionSettings, which is still called. Its own fields are untouched
(test: DerivedUserSettingsFieldsAreUntouched; a custom class is reported at Info level).
- Renderer variables that the project sets are now actually changed by TargetFrame where a feature
is enabled to change them (see the first fix). Anything that looked like it worked in 0.4.0 because
the write was dropped will now take effect.
- For players on the engine’s project-default resolution (every fresh profile), the governor’s
resolution lever now moves, and Status.ResolutionScale reports the resolved percentage instead
of 0. Code that treated ResolutionScale == 0 as “default” should read
bResolutionScaleIsProjectDefault.
Sample: Overclock 
The TargetFrame Sample plugin’s demo is now Overclock, a short arcade game whose arena gets
heavier every level (more shadow-casting lights, effects and geometry) while TargetFrame holds the
frame rate, with a live policy HUD, the new graphics screen, CC0 music and sound, and a capture
timeline for Movie Render Queue. See the sample’s README.
- The runtime monitor and showcase banner are Slate widgets now, not canvas drawing, so Movie
Render Queue’s UI pass captures them. They sit in the player’s viewport layer, under the
TargetFrame panel rather than over it. tf.DebugHUD still toggles the monitor.
- The showcase lit correctly again under Lumen. After the project moved to Lumen, hardware ray
tracing and MegaLights, its sunlight-scale key light and uncapped exposure washed the scene out to
white; it now uses a dusk-level key light, a captured sky light and bounded histogram exposure.
- Capture variants for tutorial footage:
-OverclockGovernorDemo (the governor acts on the
render’s fixed 60 FPS against a 90 goal, then the goal drops to 45) and -OverclockLightingTour
(TargetFrame’s lighting modes stepped through ApplyPlayerSettings). One MRQ preset per video, each
overriding MRQ’s game mode with the map’s own.
- Unattended review for any sample map:
-ReviewShots, -ReviewQuitAfter and -ReviewExec,
whose entries can be timed (12@TargetFrameShowPanel). Screenshots are the engine’s own frame, and
the subsystem writes them itself from the viewport’s capture delegate. UE 5.5 writes a requested
screenshot only when screenshot tracing is compiled in, and it is not in Shipping, so 5.5 Shipping
builds silently saved none.
In Shipping the command line cannot pick the map (the engine ignores it), so reviews travel with
-ReviewExec="open <map>|...".
- Overclock’s TargetFrame strip is right-aligned: centred, it ran into the dash readout once the
sparkline was visible.
Tests
41 tests: 16 PolicyMath (3 new, lighting), 21 Runtime (10 new: lighting, player settings, user
settings round trip, derived settings, custom-class reporting, HWRT clamp, preset recognition,
session-only saving, project-default resolution), 4 Soak.
Verification
Four-engine gate r4, 2026-09-27: re-run after the sample’s review screenshots moved to the capture
delegate. Clean tree per engine (RTX 5060 Ti, Windows 11). All 41 tests passed everywhere. On 5.6, the
-game log ended right after the session stopped, without its “EXIT CODE: 0” line, and there was no
crash report; a 5.6 re-run was clean on every row. The same table held for r3.
| Check |
5.5.4 |
5.6.1 |
5.7.4 |
5.8.3 |
| ScalabilityEditor Win64 Development |
0 warn* |
0 warn* |
0 warn |
0 warn |
| Scalability Win64 Development |
0 warn* |
0 warn* |
0 warn |
0 warn |
| Scalability Win64 Shipping |
0 warn* |
0 warn* |
0 warn |
0 warn |
Automation RunTests TargetFrame, -game |
41/41 |
41/41 |
41/41 |
41/41 |
| BuildCookRun cook + stage + pak + archive |
0 cook warnings |
0 cook warnings |
0 cook warnings |
0 cook warnings |
| Automation RunTests TargetFrame, packaged |
41/41 |
41/41 |
41/41 |
41/41 |
* The only notice is the toolchain’s “compiler is not a preferred version” on 5.5 and 5.6.
Fab packages (Scripts/PackageTargetFrameFab.ps1), compiled from the staged files twice:
- Non-unity:
-StrictIncludes, i.e. no PCH and no unity.
- Unity: Fab’s settings,
bUseUnityBuild true and adaptive unity off. A unity leg passes only if its
module really compiled as a unity blob.
| Leg |
5.5.4 |
5.6.1 |
5.7.4 |
5.8.3 |
| TargetFrame, BuildPlugin Win64 |
pass / pass |
pass / pass |
pass / pass |
pass / pass |
| TargetFrame, BuildPlugin Linux |
pass / pass |
pass / pass |
pass / pass |
pass / pass |
| TargetFrame, BuildPlugin Android |
pass / pass (NDK r25b) |
pass / pass |
pass / pass |
pass / pass |
| TargetFrameSample, editor Win64 |
pass / pass |
pass / pass |
pass / pass |
pass / pass |
| TargetFrameSample, game Linux |
pass / pass |
pass / pass |
pass / pass |
pass / pass |
| TargetFrameSample, game Android |
pass / pass (NDK r25b) |
pass / pass |
pass / pass |
pass / pass |
Each cell reads non-unity / unity.
Every pass is real compile actions for that platform with 0 warnings.
Shipping, packaged, run (Scripts/RunShippingValidation.ps1, 2026-09-27):
- A Shipping build has no logging and no automation tests. Each package was therefore judged on its
warnings, a run that stays up, exits 0 and leaves no crash report, and screenshots.
- The screenshots are of the runtime monitor and the experience panel on the showcase map. They show
TargetFrame’s live profile, tier, goal, frame rate, quality, render scale, lighting and events.
| Shipping |
5.5.4 |
5.6.1 |
5.7.4 |
5.8.3 |
| Win64 package |
0 warn* |
0 warn* |
0 warn |
0 warn |
| Win64 run |
7 shots, exit 0 |
7 shots, exit 0 |
7 shots, exit 0 |
7 shots, exit 0 |
| Linux package (cross-compiled) |
0 warn* |
0 warn* |
0 warn |
0 warn |
| Linux run (WSL, lavapipe) |
7 shots, exit 0 |
7 shots, exit 0 †|
6 shots, exit 0 |
7 shots, exit 0 |
| Android package (ASTC, arm64) |
0 warn* |
0 warn* |
0 warn |
0 warn |
On Linux, TargetFrame correctly reports hardware ray tracing as Clamped on lavapipe, and the governor
tightens culling at about 1 FPS.