A project picks up near identical base materials over time. Someone needs the crate in a different brown, duplicates M_Crate and changes one constant. Two years and four artists later there are three hundred base materials that are structurally about eleven, and each one is a separate shader with its own compile time and package size.
Unreal ships nothing that finds this. Material Analyzer compares instances that already share a parent, and only their static parameters, so two separate base materials are never compared to each other at all. Size Map tells you what an asset costs. Reference Viewer tells you what points at what. None of them compare the graphs, and if your project doesn’t have instances yet then Material Analyzer gives you nothing at all.
This plugin hashes the expression graphs themselves. Where a group differs only in its texture samplers and its scalar or vector constants it generates one master with those leaves promoted to parameters, converts every duplicate into an instance carrying its own original values, and repoints every referencing mesh slot. Editor plugin or headless commandlet.
The scan is two stage on purpose. Stage 1 buckets every material from asset registry tags with nothing loaded. Stage 2 loads only the members of buckets holding two or more entries. The report prints both numbers, for example examined 12,000 and loaded 340, so you can see it is not blanket loading your content browser. Loading ten thousand materials to inspect a graph is a twenty minute editor hang.
The dangerous failure here is not a crash, it is a false merge that quietly changes one prop and goes unnoticed for a month. So every ambiguity resolves toward not collapsible. An expression class the walker will not hash withdraws the whole material rather than hashing as some node. A cycle withdraws it. Anything that changes the shader permutation rather than a value withdraws it, so static switches, static bools, static component masks and material attribute layers are all out. Floats are hashed by their exact IEEE 754 bits, never by decimal formatting, because formatting rounds and two materials differing below the printed precision would otherwise hash equal and get merged. The report also lists what it nearly collapsed and the field that stopped it.
You get a plan file to read before anything is written, and a rendered proof sheet per merge group showing the group before and after.
UE 5.8, Windows, full source included.
Disclosure: this is built with AI assistance, and the code and the art are AI generated.