A downloadable tool

Buy Now$14.99 USD or more

A Movable actor that casts a dynamic shadow makes the renderer throw away its cached shadow page every time its transform changes. Most of them never move.

They were left Movable by an import default, or during a blockout, and nobody went back. On a level built by more than one person over more than one month, nobody can tell you which ones those are — and guessing is how you demote something that really does move and spend two days working out why a door stopped opening.

Shadow Thrash Fixer finds every one of them, proves which cannot move, fixes the ones it can prove, and then re-scans to show the offending set is empty.

The part to judge it on is what it REFUSES

This tool edits actors in a level you are going to ship. The dangerous failure is not missing an offender — that costs you nothing you were not already paying. It is demoting an actor that actually moves, which is a visible bug in your game that you will not connect to this plugin for days.

So every signal it reads is three-valued: established yes, established no, or unknown. There is no boolean anywhere in the model, deliberately — a boolean cannot tell "I checked and it is absent" apart from "I never checked", and code then reads a default as a decision.

Anything it cannot prove, it refuses, and the report names the exact signal it could not establish. Before it will touch an actor it must establish that all of these are absent:

  • a movement component, on the actor or any child actor
  • simulated physics — read from the authored flag, not the runtime body
  • a Sequencer binding, swept across every LevelSequence in the project
  • a Blueprint writing its transform
  • a movable parent, walked up the attachment chain
  • a pawn-like archetype
  • an unreadable native class — its C++ could move it in Tick, and we cannot see that

That last one is why the plugin uses an allow-list of native classes known to be inert, never a deny-list of classes known to move. A deny-list silently admits every class nobody thought of — including every class in your project. If your class is not on the list you get a refusal naming it, not a fix.

A short refusal list is not the goal. An honest one is.

It shows its working

The output is a proof sheet, not a table of counts. One row per actor, six marks per row, one mark per movement mechanism the tool established is absent. All six have to be filled before anything is written, so you can read the page at a glance and see why each verdict came out the way it did.

The number at the bottom is a second opinion, not a victory lap

After it writes, it runs a completely independent second scan and reports the result of that rather than its own count of successful edits.

That is not decoration. The fix pass's own success count is a claim; the re-scan is the evidence, and the two are capable of disagreeing. They did. While this product was being built, that re-scan caught a real defect in the repair path that a clean compile, a full green test suite and a passing fixture check had all missed. If they ever disagree on your project, the report says so and tells you plainly not to trust the applied count.

Two repairs, and you choose

  • Mark the shadow cache Static (the default) — sets Shadow Cache Invalidation Behavior to Static on each primitive that casts a dynamic shadow. That is the engine's own switch for suppressing invalidations caused by transform changes. It does not change Mobility, does not change whether anything casts a shadow, and needs no lighting rebuild.
  • Demote Mobility to Static (-Demote) — the deeper fix. A Static actor participates in baked lighting, so on a map whose lighting has not been rebuilt it can look worse until you rebuild.

It defaults to the narrow one and offers the demotion explicitly. It will not silently change your map's lighting.

Nothing is written unless you ask twice

-Apply on its own is a dry run: it re-proves every actor and reports what it would do. -Execute without -Apply is refused rather than interpreted, because guessing which half you meant is guessing about writes to a shipped level.

CI

Every mode runs from the headless commandlet, so a build machine can fail on regression without opening the editor. -Budget=N exits 1 when more than N actors are provably still and unfixed. The plan is written as JSON beside the report, so a build step can read it without parsing HTML.

Two things it does not claim

  • Per-actor invalidation counts. The engine exposes shadow-cache counters in aggregate only. This reports which actors are structurally responsible; it does not invent a per-actor page count, and you should distrust any tool that shows you one.
  • Exhaustive Blueprint and Sequencer coverage. The sweeps cover event and function graphs and level sequence bindings. They do not cover every possible indirection — and where coverage is partial, the report says so at the top, before you read a single verdict.

Compatibility — read this before buying

  • Engine: Unreal Engine 5.8, and only 5.8. This is the only engine the plugin has been built and verified against, and it is the only version claimed.
  • Platform: Windows.
  • Type: Editor plugin + headless commandlet.
  • Levels: Standard levels and World Partition. Unloaded World Partition actors cannot be inspected, so they are reported as unloaded rather than clean — the report distinguishes the two.
  • Dependencies: none. Every module it links is an Epic engine module.
  • Source: full C++ source ships, unminified, so you can read exactly what it does before you let it write to a level.

Documentation

Full documentation, readable before you buy.

More Unreal tools from Core Systems Asset Factory

Purchase

Buy Now$14.99 USD or more

In order to download this tool you must purchase it at or above the minimum price of $14.99 USD. You will get access to the following files:

shadow-thrash-fixer-ue5-plugin.zip 80 kB
Version 1.0.1

Development log

Leave a comment

Log in with itch.io to leave a comment.