Getting a MetaHuman from four sessions down to one
A town needs people in it. Not one hero character — thirty-odd of them, each recognisable, each dressed differently, each walking a daily routine. For weeks a single character cost roughly four working sessions, and most of that was not modelling or art. It was rediscovering the same silent failures.
By the middle of August that had come down to one session, sometimes less, and the difference was not skill. It was that every trap had been written down as a symptom, and that most of the manual steps had been replaced by scripts that a new character can be fed to as a parameter rather than a project.
This is that pipeline, and the bills that paid for it.
The shape of it
Four phases, in this order, and the order is load-bearing:
A — the MetaHuman itself. Duplicate an unused preset face, set the body with parametric constraints, stamp skin, eyes and grooms, then run the two paid cloud stages (auto-rigging and texture sources) and build. About fifteen minutes of scripted work plus a couple of minutes of waiting.
B — the wardrobe, in Blender. The MetaHuman plugin ships 38 hairstyles and exactly one garment. That single fact is why the entire clothing programme is a modelling job rather than a shopping trip. Garments are generated parametrically from the character's own exported body — measured off the mesh and the bone positions, not authored by hand.
C — dressing, back in Unreal. Import each garment onto the shared skeleton, add it as a component on the character's Blueprint, compile.
D — the routine. Give the finished NPC somewhere to be at each hour of the day.
The tooling is Unreal 5.8 driven from two editor automation servers — one for Blueprint graphs, assets and actors, one that reaches animation, audio, UI and editor Python — plus Blender in headless batch mode for the garments. The project itself contains no C++.
The trap: the clothes slide off the character the moment it moves
This is the one that cost the most, and it is the one worth searching for.
The symptom: a garment sits perfectly in the reference pose. Fitted, correct, no penetration. Press play and the hem rides up off the waistband, the collar climbs to the chin, and the shoulders punch through the fabric. It reads as bad skinning or a bad export, so that is where the time goes.
It is neither. A garment and a body can share one Skeleton asset and still each carry their own reference pose. Skinning evaluates against the component's own inverse bind matrices. So a garment set to evaluate its own animation poses itself on the proportions of the body it was fitted to, while the wearer poses on theirs, and the two drift apart by the difference between the two binds — every frame, at every bone.
The measurement that settled it, on a walk cycle:
| garment component configuration | worst bone divergence | |---|---| | its own single-node animation | 49.09 mm (83 mm at some phases) | | leader-posed to the body | 0.00 mm, every bone, every phase |
Two independent instruments agreed to within a hundredth of a millimetre: the bind deltas computed from the exported files in Blender, and the live component transforms read out of the running editor.
The fix is to make the garment a follower of the body's pose rather than an animator in its own right. On a MetaHuman-derived Blueprint you do not even have to ask for it — the construction script already does it for any skinned component parented under the body. So the whole dressing step reduces to: parent the garment under the body, and stop. The previous documented step, which explicitly switched the component into single-node mode with an idle clip, was actively creating the bug it was written to avoid.
Why it hid for so long: the first NPCs in the project all wore garments fitted to their own bodies, or wore a shared kit on the exact body that kit was built from. A matched pair diverges by zero. The bug only exists when a garment crosses bodies — which is precisely what you start doing the day you decide to dress a whole cast from a shared wardrobe.
Two guards came out of it. First, the comparison rig is a script, not a look: it prints per-bone divergence with no play session and no viewport, so the question "is this garment following correctly?" has a number rather than an opinion. Second — and this nearly caused a wrong diagnosis — you cannot toggle back to compare. Clearing the follower link does not restore independent evaluation; it leaves the component dead with every bone collapsed onto the actor origin, which renders as clothing heaped on the floor and looks like a catastrophic failure. To compare configurations, respawn the component.
The other bills, each in one paragraph
"My character came out bald after assembling." Assembly guts hair to a one-curve stub. Not occasionally — on this machine it is the default outcome, and a batch of sixteen came back damaged sixteen times out of sixteen. Groom repair is therefore a scheduled pipeline step, not a fix-up. Worse, an audit that counts missing assets finds only about a quarter of them, because a gutted groom still exists; it just has one curve where the source has a hundred thousand. Only comparing curve counts against the pristine source sees the truth.
"The beard looks right close up and ginger at a distance." Groom colour lives on material instances generated at assembly time, and any instance that never gets an explicit override inherits the parent's defaults — melanin 0.80 and, the real culprit, a redness of 0.25. On a dark-haired character that warmth is a nuance. On a grey-haired one there is almost no pigment left for it to tint, so it reads as ginger. The instances that got missed were the card and helmet variants used at lower detail levels, hence the correct-then-wrong behaviour as the camera pulls back. Fix: enumerate the generated instances and colour all of them; never hand-list, because a hand-list is wrong in both directions at once.
"I asked for a masculine body and got a woman." The Masculine/Feminine body constraint runs from −2 to +2 and the minimum end is masculine. Every male build in this project sets a negative value. Setting +2 for a man produces the opposite of what you asked for, with no warning, and the default archetype is female if you specify nothing at all.
"The preset's shirt came back after I removed it." Clearing the outfit slot succeeds and verifies clean, and then the commit calls that follow — face, body, skin — each rebuild the item collection and quietly restore it. A build that assembles clothed culls the torso and can never be dressed properly afterwards, so this destroys the character silently. The strip is now a function called three separate times, the last two fatal on failure.
"Eleven men with their toes poking out of their boots." Three faults stacked, and the last one is the honest lesson. Uniform scaling of a component scales about its origin, which for a garment parented at the body root is on the floor between the feet — so shrinking a boot to 0.93 also drags its toe about a centimetre backwards. The first correction pinned the wrong axis: the foot points along +Y, and the axis that was pinned is the one that is antisymmetric between left and right, so it pulled the women's shoes sideways off their feet. And the scale was being solved from the ball of the foot rather than the toe, which under-runs the real foot length by more than two centimetres — two characters had toes out at a scale of exactly 1.0, where no amount of repositioning could ever help.
The audit script for that reported "0 wearers short — all clear" the entire time the developer was looking at eleven men with their toes out. Two mechanisms, both worth recognising anywhere: it only flagged a wearer when no correction had been written, never whether the correction was right, so it went silent the moment anything was applied, working or not. And it guessed which axis pointed forwards, producing a full table of confident wrong numbers. A check that stops checking once you have done something is not a check, and an axis you assumed is a measurement you did not take.
"The boots are crumpled at his feet after reloading the level." Garment components hung directly on a placed actor survive a level reload; every property configured on them does not. The construction script re-runs on load and re-asserts the body from the class default, which clears the follower links on everything parented beneath it. Garments belong on a Blueprint, never on a placed instance.
Two ways to hard-crash the editor mid-build. Leaving a play session running while the local build runs: with a live game world, the asset importer takes its runtime path, refuses the editor-only skeletal mesh import, and both archetype face and body meshes come back null. Separately, running the cloud stage through the automation server crashes inside the auto-rigging request regardless of any flag — that route was tested directly and the question is closed; the cloud stage runs from the editor's own menu, driven by mouse automation, and takes about two and a half minutes per character. The mitigation that matters is structural: split the build into a configure stage and a cloud stage and save between them, and again between the cloud calls and the local build. A crash used to discard both paid results and fifteen minutes of local configuration. With the saves in place, a failed build is a free local re-run.
What is still not proven
The often-quoted performance figure for these characters — a fraction of a millisecond of GPU time each — was measured here, but every caveat still stands: the twenty characters in that test were clones sharing meshes and textures, they were not animating, and they had no clothing. A roster of unique characters against an 8 GB video memory budget has never been measured, and video memory remains the live ceiling on this machine, not frame time. Several individual outfits also have known open defects; a repeatable pipeline is not the same claim as a finished cast.
What to take from it
- **A recipe that duplicates a living reference will rot into a trap, because nothing
recompiles a checklist.** Two hand-written character runbooks here both drifted into teaching the exact step that caused the garment bug. Durable recipes now live in one place that gets loaded every session.
- Print a number between passes, not just at the end. Every one of the fitting faults
was found by an intermediate count, never by looking at a render. A total at the end could have come from anywhere.
- Distrust any check that can only pass. Two audits in this work reported all-clear
while the fault was plainly visible on screen — one because it measured whether a fix had been attempted rather than whether it worked, one because it guessed an axis.
- A trap that only fires on some inputs will hide indefinitely. The garment drift is zero
when a garment is worn by the body it was fitted to; the fitting faults were invisible while the code had only ever run on one man. Run the same code across the whole set early.
- Order destructive and expensive steps so a failure is cheap. Save before and after
anything you paid for, and gate optional stages with a flag rather than an early return — an early return skips the save too.
- The dangerous failures are not crashes. They are the calls that return success, read
back plausibly, and change nothing.