unreal-pipeline-automation
Unreal pipeline automation (pipeline and tools TD)
Version 0.1 (2026-09-24), part of Unreal Engine Expert Skills v0.1.
Expert pipeline work in Unreal is policy as data plus proof: the import policy is a versioned pipeline asset, names come from a plan, every rule that matters is a validator that also guards human edits, and a build counts once it cooked with fatal validation and booted. Bulk work runs headless; anything visual goes to a screenshot someone actually looks at.
REQUIRED BACKGROUND: unreal-expert (channels, review loop, 5.8 traps).
Status (2026-09-24): every Unreal call here is not yet run in Unreal; the pure layer of scripts/ue_pipeline.py and both jobs ran offline (unit tests, plus control flow against a fake unreal). First action once 5.8 is installed: tests/code/unreal-pipeline-automation/in_engine/run_in_unreal.py.
Stance (the expert delta)
- Import policy is an asset you pass, never dialog memory, and it sticks to the asset. Scripted imports use the pipeline's defaults, not what the dialog last remembered (Interchange PM, Oq6KbrqkGnw [00:39:28]; Jamie Dale, 0guOMTiwmhk [01:26:38]): duplicate the generic assets pipeline into the project, set every option, pass it in
override_pipelines. Stack order is execution order: a tweak pipeline above the default one sees no factory nodes [00:20:22]. Filter at factory-node level, following Factory Dependencies, so orphan materials are never created [00:31:33]; a Graph Inspector left in the stack pops up mid-batch [00:40:00]. An asset keeps its stack and reimport reuses it (Interchange doc), so a policy change reaches existing assets only through a reimport that passes the new preset (plan_imports(..., policy=)). - Names come from the plan, not the importer. Interchange ignores
AssetImportTask.destination_name(5.8 API reference). Stage each file under its target name and rename only as a fallback: a rename leaves a redirector (naming doc), and the Zen loader ignores core redirects. Renaming onto an existing asset fails, which is how re-runs leave duplicates: reimport instead (I03). No drag and drop: other tools depend on paths (Bardoux, MjjkWH0eT3U [00:09:14]). - Nanite by eligibility, not triangle count. Opaque or masked static meshes on a Nanite target get Nanite, low-poly included: non-Nanite geometry is "much more expensive to render into VSMs" (VSM doc). Off for translucent materials (Nanite draws the default material), morph targets and non-Nanite targets; "not everything can be Nanite" (Oztalay, S2olUc9zcB8 [00:34:33]). Fallback settings on every Nanite mesh (DxBKmQ-0kfw [00:37:15]); simple collision still required.
- Validation is code at the point of creation, and red must mean new. About 30 to 40 percent of bugs trace back to something an asset validator could catch (Fray, KuIWCzujtag [00:35:40]). Keep
CanValidateAssetcheap [00:31:47] and watch each validator's cost in 5.8's per-validator cook stats (DataValidation.ReportCookValidationStats); allow-list legacy errors [00:38:07]; see each check fail on a fixture first [01:46:04]. Python validators register every session,-run=DataValidationruns C++ rules only, and cook validation without-ValidationErrorsAreFatalturns errors into warnings. - Headless for bulk, the open editor for what it holds, and no trust in exit codes. The commandlet loads no level (Python doc) and the registry may still be scanning:
wait_for_completion()before queries (5.8 batch example). A Python failure only logs an error unless-ScriptErrorsAreFatal(5.5): the verdict is the job's own result line (P.job_verdict). The editor keeps a write lock on loaded assets (Jamie Dale [01:17:18]): run inside it through MCP or Python remote execution.set_editor_propertybehaves like the Details panel; plain attribute writes rebuild nothing [00:21:25]. Under Perforce, 5.8's PythonScript commandlet enables source control first; check out what you will save and stop if checkout fails (Bardoux [00:55:27]). Imports are not undoable: snapshot first. - List, confirm, act, one pass per mesh. Print the resolved targets, then run (Sam Deiter, k0tgmrBuIJc [00:52:23]). Set Nanite, LODs and collision in one pass and save once per chunk. A LOD group may not build LODs by itself [verify]: count after setting it, build the chain explicitly if short, check screen sizes decrease (L02). One bad file never stops the batch.
- A build is a reproducible command line, proven by booting. Generate the BuildCookRun line once from a Project Launcher profile and diff yours against it (UAT doc;
P.buildcookrun_diff). Cook does not stage,-skipcookis not omitting-cook(Josh Adams, uxdEt9XXKb8 [00:19:14], [00:20:20]); Xcode assembles the.appwhether or not anyone edits in Xcode [00:03:33] (that content-only projects need full Xcode is an inference to verify). Same command locally and on CI (Hamilton, 3ftOkc-cA7U [00:25:15]); then boot it (GauntletUE.BootTest) and stay to watch (Ari, 102O0FOEzNY [00:39:07]). Performance numbers are trends, not gates (Fray [01:29:38]).