UE_BUILD_AUTOMATION.md

pipelines/UE_BUILD_AUTOMATION.md

Unreal Engine Build Automation — Technical Research Brief

Compiled 2026-07-15. Scope: the autonomous/programmatic build surface of the current Unreal Engine release, evaluated against this project's pipeline — a typed story spine (site rows, boss phase maps, scene rows, fork tables) plus CSV canon registries (bosses 282 rows, creatures 132 rows, weapons, etc.) driving an eventual playable build across ~69 regions.

How to read this document

---

Executive summary of the headline findings

1. UE 5.8 is correct. It shipped ~mid-June 2026 (announced at Unreal Fest Chicago / State of Unreal 2026) and is explicitly the last planned major UE5 release — Epic is now ramping UE6 (Early Access targeted end of 2027, full release 12-18 months after). Build on 5.8; plan a UE6 evaluation for late 2027, not sooner.

2. UE 5.8 ships an official, Epic-authored, Experimental "Unreal MCP" plugin that names Claude explicitly as a supported LLM for driving the editor (including a dedicated PCG toolset). This is Epic's own sanctioned answer to this project's exact goal, but it is Experimental and positioned as supervised/assistive, not a deterministic backbone.

3. The deterministic automation spine is real and largely mature: Python 3.11.8 embedded scripting, headless commandlets, RunUAT BuildCookRun, and Epic's own Horde CI system prove "an external agent drives the editor end-to-end with no human clicking" is an Epic-sanctioned pattern, not a stretch goal.

4. The one genuine hole in pure-Python automation is Landscape heightmap import — there is no stock Python call to create a landscape from a heightmap; it requires a small C++ shim (or a third-party plugin) wrapping ALandscape::Import(). This is the single highest-priority engineering dependency in the whole chain.

5. PCG (Procedural Content Generation) is Production-Ready (since 5.7) and has first-class DataTable ingestion (Load Data Table, Data Table Row to Attribute Set) — this is the direct, verified mechanism for turning CSV registry rows into populated 3D encounter zones.

6. DataTables require one C++ USTRUCT per registry (Blueprint-only structs are rejected — Epic bug UE-152346) but are otherwise fully CSV/JSON-scriptable with zero GUI interaction.

7. MetaHuman changed architecture substantially and recently: fully in-editor since UE 5.6 (no more cloud/browser Creator app), with an official Python API for batch character creation and parametric face variation added in 5.7 and extended in 5.8 — but auto-rigging and texture synthesis still round-trip to Epic's cloud per character, an undocumented throughput bottleneck at "hundreds of NPCs" scale.

8. Sequencer is fully Python-scriptable end-to-end (create asset, camera cuts, actor bindings, tracks, keyframes) and Movie Render Queue renders headlessly from the command line with documented, verbatim invocation syntax.

9. There is no Epic-documented worldstate/save architecture for "many typed persistent flags." Lyra (Epic's flagship sample) ships no save/persistence reference at all. The 39-key ws.* architecture in Section 7 is a synthesized recommendation, not a cited Epic pattern — flag it for a validation spike.

10. Licensing is clean for a solo commercial game: free under $1M lifetime gross per product, 5% above (dropping to 3.5% or 0% depending on Epic Games Store day-and-date/payment-processor choices). MetaHuman is no longer UE-only and follows the same royalty terms.

11. The EULA's generative-AI clause is the one licensing item needing a legal read before locking the pipeline architecture — it restricts using Epic's engine/content as AI *training data*, with genuinely ambiguous community debate over "prompt-based input" wording; it does not, on the plain reading, restrict using AI to *author* your own content or *drive* the editor.

---

0. Engine version verification

[VERIFIED, converged independently across all four research passes.]

Practical implication: every API/class name below has been checked against 5.8-era documentation (not older tutorial-era assumptions). Where an agent found that a name/pattern had changed across 5.x (e.g., EditorLevelLibrary deprecation, MetaHuman's cloud-to-in-editor migration), that delta is called out explicitly rather than silently using the old name.

---

1. Python Editor Scripting + Remote Control API + headless commandlets

1.1 Python Editor Scripting

  UnrealEditor-Cmd.exe "C:\projects\MyProject.uproject" -ExecutePythonScript="C:\my_script.py"

(boots the full editor, then runs the script), or the faster, headless-oriented commandlet path:

  UnrealEditor-Cmd.exe "C:\projects\MyProject.uproject" -run=pythonscript -script="C:\my_script.py"

UnrealEditor-Cmd.exe is the console subvariant — no GUI window, logs to stdout. [FLAG — INFERRED] the exact flag spelling above is stable, widely-used community practice across 5.x, but was not re-confirmed against a specific 5.8 documentation page this session; a 1-minute live check is worth doing before wiring CI around it.

Core unreal module API surface [VERIFIED unless noted]:

1.2 Remote Control API (Web Remote Control)

[VERIFIED — https://dev.epicgames.com/documentation/en-us/unreal-engine/remote-control-for-unreal-engine]

1.3 Headless commandlets, cook & package automation

[VERIFIED unless noted]

    RunUAT.bat BuildCookRun -project="C:\path\MyProject.uproject" ^
      -noP4 -platform=Win64 -clientconfig=Shipping ^
      -cook -allmaps -build -stage -pak -archive -archivedirectory="C:\out" ^
      -nocompileeditor -utf8output -unattended -nosplash

Key flags: -cook, -build, -stage, -pak, -archive/-archivedirectory, -clientconfig=Shipping|Development, -platform=/-targetplatform=, -server+-noclient (dedicated-server build), -noP4, -utf8output. Linux: RunUAT.sh BuildCookRun … -targetplatform=Linux -cook -stage -archive -pak.

1.4 Fully headless — no display required

[VERIFIED]

1.5 Epic's own "external system drives the editor at scale" pattern — Horde

[VERIFIED — https://dev.epicgames.com/documentation/unreal-engine/horde-in-unreal-engine]

1.6 Target 1 residual unknowns

---

2. Landscape / terrain: heightmap import, World Partition, materials

2.1 Heightmap import — formats & bit depth

[VERIFIED — https://dev.epicgames.com/documentation/en-us/unreal-engine/importing-and-exporting-landscape-heightmaps-in-unreal-engine]

Supported formats for the classic Landscape (heightfield) system:

Native format is single-channel grayscale, 16 bits per pixel (0-65535, 32768 = sea level). RGB images are accepted but color is discarded and precision degrades — do not use them. 8-bit is technically accepted but causes visible terracing (256 height steps) — standardize on PNG16 or .r16.

EXR is NOT a supported classic-heightmap import format — flagged explicitly because external terrain tools (Houdini, Gaea) often default to EXR for other purposes; do not let that default leak into the heightmap export step. Third-party tools explicitly called out as supported upstream sources: Gaea, World Machine, Houdini, Terragen. Tiled heightmaps are supported (importer detects/prompts for the tiled path).

2.2 Resolution / tiling constraints

[VERIFIED — https://dev.epicgames.com/documentation/unreal-engine/landscape-technical-guide-in-unreal-engine]

Recommended landscape sizes (use these exact combinations):

Overall size (verts)Quads/sectionSections/componentComponent sizeTotal components
8129 × 81291274 (2×2)254×2541024 (32×32)
4033 × 4033634 (2×2)126×1261024 (32×32)
2017 × 2017634 (2×2)126×126256 (16×16)
1009 × 1009634 (2×2)126×12664 (8×8)
505 × 505 (default)634 (2×2)126×12616 (4×4)
127 × 127634 (2×2)126×1261 (1×1)

Pipeline implication: generate heightmaps at exactly one of these vertex dimensions. [FLAG — partially INFERRED] the modern import panel exposes Section Size / Sections-Per-Component / Component Count / Overall Resolution fields and auto-populates a nearest-fit — but a dedicated "resolution calculator" widget beyond those fields was not confirmed from public docs. Treat the table above as the reliable contract; pre-size heightmaps externally.

2.3 Programmatic heightmap import — the key limitation in the whole chain

There is no clean pure-Python path to create a Landscape and import a heightmap. This is the single biggest automation gap identified across all eight research targets.

[VERIFIED — https://forums.unrealengine.com/t/creating-a-lanscape-using-c-or-the-python-api/504997 ; corroborated https://forums.unrealengine.com/t/landscape-creation-using-the-python-api/2063596]

What actually works:

Bottom line: heightmap → Landscape actor creation must go through C++ (or a C++/Python shim/commandlet), or a third-party plugin — this is the one link in the entire pipeline requiring bespoke engine C++ rather than pure data/scripting. Budget engineering time for this specifically.

2.4 World Partition — status, grid config, automation

[VERIFIED]

Net: WP creation/grid sizing is commandlet/World-Settings-driven, not pure Python; Data Layer tagging and HLOD/navmesh builds *are* headless-automatable.

2.5 Landscape materials & layer painting

[VERIFIED — https://dev.epicgames.com/documentation/en-us/unreal-engine/creating-and-using-custom-heightmaps-and-layers-in-unreal-engine]

2.6 Landmass plugin

[VERIFIED — https://dev.epicgames.com/documentation/unreal-engine/landscape-blueprint-brushes-in-unreal-engine]

Landmass is a mature, shipping (non-experimental) plugin in 5.8, providing CustomBrush_Landmass — a Landscape Blueprint Brush generating terrain from a spline shape plus erosion/curl-noise/displacement, operating on Landscape Edit Layers. It's what the Water plugin uses to carve terrain under rivers/lakes.

Assessment: Landmass is spline-and-brush / art-directed, not a bulk data-driven generator. Brushes are Blueprint actors (scriptable spline/parameter placement is possible) but this is not a cleaner "CSV row → terrain" path than heightmap import. Reserve Landmass for hero features (a specific river, a plateau) layered atop a base landscape; use external heightmap generation for bulk, data-driven terrain.

2.7 New in 5.8 — Mesh Terrain (Experimental) — do not build on yet

[VERIFIED — https://www.unrealengine.com/news/unreal-engine-5-8-is-now-available ; https://80.lv/articles/unreal-engine-5-8-is-out-today-with-big-optimization-improvements-and-mesh-terrain]

UE 5.8 introduces Mesh Terrain, a new Experimental true-3D-mesh terrain system (vs. 2.5D heightfield Landscape) supporting overhangs/floating islands/tunnels, a non-destructive modifier stack, mesh-or-heightmap import, and full PCG/World Partition/Nanite interoperability. Recommendation: do not build the pipeline on Mesh Terrain yet — it's Experimental (API churn likely, scripting surface undocumented). Use classic Landscape now; revisit if/when Mesh Terrain reaches Beta/Production (plausibly UE6-era), especially if any regions genuinely need overhangs/caves.

2.8 Most-automatable current terrain pipeline (mapped to our site rows)

Given per-site rows (terrain_type, ambient_threat, vril_density, climactic_affordance, protected) across ~69 regions:

1. Heightmap generation (external, headless): generate a valid-sized PNG16/.r16 heightmap per region from terrain_type, via a procedural tool (Gaea/World Machine/Houdini or a bespoke noise generator) — outside the engine, easiest to script there.

2. Landscape creation (C++/shim commandlet): import via the C++ ALandscape::Import() path wrapped as a commandlet/Python-callable function (§2.3), supplying initial weightmaps for base layers. *(The one step needing engine C++.)*

3. World Partition + Data Layers (commandlet + Python): convert to WP (WorldPartitionConvertCommandlet, set CellSize), tag protected/safe-zone sites into Data Layers via DataLayerEditorSubsystem (pure Python). Build HLODs/navmesh via builder commandlets.

4. Material/layer assignment: slope/height auto-material keyed to terrain_type (no manual painting), or PCG-written layers.

5. Population (PCG, §3): CSV rows → DataTable → PCG Load Data Table to scatter flora/fauna/encounter markers by ambient_threat/vril_density/climactic_affordance, baked headlessly.

2.9 Target 2 residual unknowns

---

3. PCG (Procedural Content Generation) framework

3.1 Maturity — production-ready

[VERIFIED — https://www.unrealengine.com/news/unreal-engine-5-7-is-now-available ; https://www.tweaktown.com/news/107858/unreal-engine-5-7-preview-now-out-with-production-ready-procedural-content-generation-framework/index.html]

The core PCG Framework became Production-Ready in UE 5.7 (Experimental since 5.2, Beta since 5.4) and remains so in 5.8. 5.7 also delivered ~2× performance over 5.5, a GPU compute path, and a new PCG Editor Mode (draw splines/paint points/create volumes bound to graphs). Caveat: some adjacent pieces remain Experimental — notably PCG Biome Core (v0.2) and GPU/runtime-generation extras — verify runtime performance before shipping those specific sub-features.

3.2 Graph authoring via Python — possible, but not where the leverage is

[VERIFIED — https://dev.epicgames.com/documentation/en-us/unreal-engine/python-api/class/PCGGraph]

Python *can* author graphs, not merely trigger them: create the asset (asset_tools.create_asset('MyGraph', '/Game/PCG', unreal.PCGGraph, unreal.PCGGraphFactory())), add nodes (add_node_of_type(settings_class), add_node_copy(settings), add_node_instance(settings)), wire them (add_edge(from_node, from_pin_label, to_node, to_pin_label), remove_edge(...)), and manage them (remove_node(), get_input_node(), get_output_node()).

Precise distinction: this is a low-level, sparsely-documented surface, tedious/brittle for complex graphs. The reliable, recommended pattern: author reusable template graphs once in the visual PCG Editor, expose tunable knobs as graph parameters/user attributes, and use Python/data only to instantiate, parameterize, and execute them per site. Treat visual authoring as the design tool; Python as the orchestration tool.

3.3 Runtime/execution model — including headless bake

[VERIFIED — https://dev.epicgames.com/documentation/en-us/unreal-engine/procedural-content-generation-overview ; https://dev.epicgames.com/documentation/en-us/unreal-engine/using-pcg-generation-modes-in-unreal-engine]

  UnrealEditor.exe "Project.uproject" "/Game/Maps/MyOpenWorld" \
    -run=WorldPartitionBuilderCommandlet -Builder=PCGWorldPartitionBuilder \
    -IncludeGraphNames=PCG_GraphA;PCG_GraphB \
    -Unattended -AllowCommandletRendering

Flags: -IncludeGraphNames= (filter to specific graphs), -IterativeCellLoading/-IterativeCellSize= (memory management), -Unattended, -AllowCommandletRendering. https://dev.epicgames.com/documentation/unreal-engine/world-partition-builder-commandlet-reference ; https://forums.unrealengine.com/t/world-partition-pcg-builder/2730237. This maps to Epic's public roadmap item "PCG Offline Builder" and is the intended mechanism to bake all PCG content in a build step. [FLAG] community reports note edge-case bugs (iterative-cell-loading + a Grid Size node can throw an executor error); pin engine version and test the specific graphs.

3.4 External data → PCG — the core mechanism (strong, verified answer)

[VERIFIED — https://dev.epicgames.com/documentation/en-us/unreal-engine/procedural-content-generation-framework-node-reference-in-unreal-engine]

PCG has first-class DataTable ingestion — directly the "CSV row → populated zone" mechanism this project needs:

Roadmap context (not blocking): Epic's public roadmap lists further refinements — "Attribute Set Tables," "Native Level to PCG Data Asset," "PCG Offline Builder." The shipping Load Data Table + Data Table Row to Attribute Set nodes already cover the core need in 5.8. [FLAG] exact ship-versions of those roadmap cards were not fully determinable (productboard cards didn't fully load) — the shipping nodes themselves are confirmed in the 5.8 node reference, which is what matters for now.

3.5 Documented data-driven scatter pattern

Recommended shape for this project: import creature_registry.csv and boss_registry.csv as DataTables; per region, Data Table Row to Attribute Set yields that site's spawn spec; a template graph reads ambient_threat → spawn density, vril_density → creature-tier filter, climactic_affordance → boss/set-piece marker placement, protected → suppress hostiles (or route via the Data Layer, §2.4). Boss "encounter markers" are cleanest as PCG-spawned trigger/spawner actors rather than baking live AI directly (see §9 Step 8 on why the boss's actual fight logic is a separate, non-PCG concern).

3.6 Unreal MCP plugin — directly relevant to the "AI pipeline" goal

[VERIFIED — https://dev.epicgames.com/documentation/unreal-engine/working-with-pcg-and-llms-using-unreal-mcp-in-unreal-engine]

UE 5.8 ships an Experimental Unreal MCP server giving "LLM-driven access to Unreal Engine," with a dedicated PCG toolset: an LLM (explicitly Claude, per Epic's docs) can do graph manipulation/generation, node wiring, parameter config, and attribute-driven data-flow through it. Requirements: enable the MCP plugin, load the PCG toolset, and load the "PCG graph generation skill" (Epic calls this *mandatory* — without it the LLM "misunderstands PCG concepts, overcomplicates, misuses nodes"). Limitations: Experimental; intended for supervised collaboration, not autonomous execution; large-graph analysis is resource-expensive; no direct attribute inspection (needs a "Dataview" workflow).

Assessment: promising and on-mission, but Experimental and supervision-oriented. For a reliable, repeatable ~69-region pipeline, the deterministic path (DataTable → template PCG graphs → PCGWorldPartitionBuilder bake) should be the spine, with the MCP plugin used for one-off graph authoring/iteration rather than the production backbone.

3.7 Target 3 residual unknowns

---

4. Data ingestion — DataTables/DataAssets from CSV/JSON, GameplayTags

4.1 DataTable CSV import — format requirements

[VERIFIED — https://dev.epicgames.com/documentation/en-us/unreal-engine/data-driven-gameplay-elements]

4.2 Blueprint-only row structs — NOT supported (hard finding)

DataTable row structs must be C++ USTRUCTs deriving from FTableRowBase. Blueprint User-Defined Structs (UUserDefinedStruct) are rejected by the importer and the "Add Data Table Row" node. Epic tracks this as bug UE-152346. [VERIFIED — https://issues.unrealengine.com/issue/UE-152346]

USTRUCT(BlueprintType)
struct FBossRow : public FTableRowBase {
    GENERATED_BODY()
    UPROPERTY(EditAnywhere, BlueprintReadWrite) FText DisplayName;
    UPROPERTY(EditAnywhere, BlueprintReadWrite) TArray<FBossPhase> Phases;
    UPROPERTY(EditAnywhere, BlueprintReadWrite) FDataTableRowHandle ThreadRef;
};

Implication: a thin C++ layer of struct definitions is required — one USTRUCT per registry. This is pipeline-friendly: those headers can be auto-generated from the CSV/markdown schema by the ingestion tool itself, so the "C++ requirement" becomes one generated header per registry (compiled once), not hand-authoring per registry. [INFERRED — reasonable extension; codegen of USTRUCT headers is a known technique, but no official Epic generator was found for it.]

4.3 Fully script-driven DataTable creation & import (zero GUI)

[VERIFIED against the 5.8 Python API]

(a) Create the asset + first import:

csv_factory = unreal.CSVImportFactory()
csv_factory.automated_import_settings.import_row_struct = unreal.load_object(None, "/Script/YourModule.BossRow")

task = unreal.AssetImportTask()
task.filename         = r"C:/export/bosses.csv"
task.destination_path = "/Game/Data/Bosses"
task.destination_name = "DT_Bosses"
task.replace_existing = True
task.automated        = True      # suppresses all dialogs
task.save             = True
task.factory          = csv_factory

unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([task])

Confirmed classes/props: unreal.CSVImportFactory, .automated_import_settings.import_row_struct, unreal.AssetImportTask (filename/destination_path/destination_name/replace_existing/automated/save/factory), unreal.AssetToolsHelpers.get_asset_tools().import_asset_tasks([...]). Also unreal.DataTableFactory (with .struct) for creating an empty typed DataTable. https://github.com/Kympy/Unreal_CSV_To_DataTableAsset/blob/main/asset_generator.py ; class existence corroborated at https://dev.epicgames.com/documentation/en-us/unreal-engine/python-api/class/DataTableFactory

(b) Fill/refresh an existing DataTable via unreal.DataTableFunctionLibrary (5.8-confirmed):

Headless/CI: run either via a commandlet, e.g. UnrealEditor-Cmd.exe <Project.uproject> -run=pythonscript -script="ingest.py" — the whole ingest becomes a build-script step with zero editor UI. [INFERRED — standard pattern, exact flag spelling not re-verified against an official 5.8 page this session.]

4.4 Re-import behavior & reference preservation — important for a living CSV pipeline

4.5 DataAssets / Primary Data Assets, and the JSON path

4.6 GameplayTags — authoring & bulk registration

[VERIFIED — https://dev.epicgames.com/documentation/en-us/unreal-engine/using-gameplay-tags-in-unreal-engine]

1. Config INIConfig/DefaultGameplayTags.ini plus any .ini under Config/Tags/, syntax +GameplayTagList=(Tag="Boss.Phase.Enrage",DevComment="..."), gated by the "Import Tags From Config" project setting.

2. DataTable with row type FGameplayTagTableRow — importable as CSV/JSON like any other DataTable.

3. C++ native tagsUE_DECLARE_GAMEPLAY_TAG_EXTERN / UE_DEFINE_GAMEPLAY_TAG(_COMMENT) from NativeGameplayTags.h.

4.7 Concrete pipeline for 282 bosses + 132 creatures, and the impedance mismatches

Happy-path pipeline (fully scriptable, near-zero clicking):

1. Author/codegen one C++ USTRUCT : FTableRowBase per registry (FBossRow, FCreatureRow, FThreadRow, …).

2. Emit each registry as JSON (not CSV) if it has nested/array fields (e.g., boss phases); flat CSV otherwise.

3. Run a headless Python commandlet: CSVImportFactory/AssetImportTask to create DT_Bosses, DT_Creatures, …, then DataTableFunctionLibrary.fill_data_table_from_json_file for refreshes.

4. Generate Config/Tags/*.ini for any tag taxonomy in the same run.

Impedance mismatches to design around:

4.8 Target 4 residual unknowns

---

5. MetaHuman — current state and automation limits

5.1 Current architecture — the big change is real and recent

MetaHuman Creator is now fully integrated into the Unreal Editor, as of UE 5.6 (shipped June 3, 2025). The old separate browser-based/cloud "MetaHuman Creator" web app is gone, and Quixel Bridge is no longer the delivery mechanism.

[VERIFIED]

Names to know: MetaHuman Creator plugin, MetaHuman Creator Core Data, MetaHuman Character asset, MetaHuman Animator, Mesh to MetaHuman.

5.2 Automation — can MetaHumans be generated/varied programmatically? (the single most important finding for this target)

This changed materially and recently: the honest current answer is "substantially yes, within the MetaHuman parametric model" — different from the pre-5.7 world where creation was purely manual/GUI.

[VERIFIED]

The precise, honest distinction for pipeline design:

5.3 The DNA format / MetaHuman SDK

The DNA format is documented with an open-source SDK — but it modifies existing DNA, it does not generate novel faces.

[VERIFIED]

5.4 Animation pipeline — the bright spot

[VERIFIED]

5.5 Practical scale limits + the hero/crowd pattern

Epic's own documented architecture is exactly the tiered pattern this project needs: full MetaHumans for hero/named, a separate crowd system for the masses.

[VERIFIED]

5.6 Target 5 residual unknowns

---

6. Sequencer / cinematics automation

6.1 Can Level Sequences be built entirely programmatically via Python? Yes.

[VERIFIED — https://dev.epicgames.com/documentation/unreal-engine/python-scripting-in-sequencer-in-unreal-engine]

The full create → bind → track → key → range surface is scriptable:

Bottom line: yes — create a Level Sequence, add camera-cut/transform/skeletal-animation/audio/subsequence tracks, bind participants as possessables or spawnables, key transforms/properties, and set the playback range, entirely from Python.

6.2 Generating a Level Sequence from external structured data (the central question)

Honest answer: there is no turnkey Epic "table/JSON → Level Sequence" feature — but the complete Python surface to build that translation layer exists, and doing so is established professional practice.

6.3 Headless rendering via Movie Render Queue — yes, fully documented

[VERIFIED — https://dev.epicgames.com/documentation/unreal-engine/using-command-line-rendering-with-move-render-queue-in-unreal-engine]

Verbatim examples from Epic's 5.8 docs:

Render one Level Sequence with a preset config:

UnrealEditor-Cmd.exe "E:\SubwaySequencer\SubwaySequencer.uproject" subwaySequencer_P -game -LevelSequence="/Game/Sequencer/SubwaySequencerMASTER.SubwaySequencerMASTER" -MoviePipelineConfig="/Game/Cinematics/MoviePipeline/Presets/SmallTestPreset.SmallTestPreset" -windowed -resx=1280 -resy=720 -log -notexturestreaming

Render a whole queue asset:

UnrealEditor-Cmd.exe "E:\SubwaySequencer\SubwaySequencer.uproject" subwaySequencer_P -game -MoviePipelineConfig="/Game/Cinematics/MoviePipeline/Presets/BigTestQueue.BigTestQueue" -windowed -resx=1280 -resy=720 -log -notexturestreaming

Custom Python executor (for a fully scripted pipeline):

UnrealEditor-Cmd.exe "E:\SubwaySequencer\SubwaySequencer.uproject" subwaySequencer_P -game -MoviePipelineLocalExecutorClass=/Script/MovieRenderPipelineCore.MoviePipelinePythonHostExecutor -ExecutorPythonClass=/Engine/PythonTypes.MoviePipelineExampleRuntimeExecutor -windowed -resx=1280 -resy=720 -log -notexturestreaming

Notes:

6.4 Mapping the §13 scene-row schema onto Sequencer

Schema: scene_anchor_id | beat_ref | scene_type | path_bucket | anchor_type | participant_refs | thematic_anchor. Realistic translation layer [INFERRED, each grounded in the verified API above]:

What in the schema has NO clean automatable Sequencer equivalent — flag these for pipeline design:

1. Per-shot camera blocking, timing, and cut rhythm are not in the schema at all — they must come from the scene_type templates (or a separate heuristic/LLM authoring step). The schema tells you who/what/where/why, not how the camera moves. This is the single biggest gap between "scene row" and "finished cinematic"; templates are the intended bridge.

2. Actual performance content — specific body animation and facial performance per beat — isn't in the schema; it must come from the Target-5 animation pipeline (retargeted mocap library + audio-driven facial from dialogue SoundWaves). The scene row references participants; it doesn't contain their motion.

3. Dialogue/audio assetsparticipant_refs implies who speaks, but the schema carries no line/audio reference. A separate dialogue→SoundWave source is needed to populate audio tracks and drive MetaHuman Animator's audio-driven facial mode. This is a genuine schema gap worth closing if auto-populated audio + lip-sync is wanted.

6.5 Target 6 residual unknowns

---

7. Save-game / worldstate architecture patterns

7.1 USaveGame — current architecture & the "many flags" gap

[VERIFIED — https://dev.epicgames.com/documentation/en-us/unreal-engine/saving-and-loading-your-game-in-unreal-engine]

7.2 Centralized "world state subsystem" pattern

[VERIFIED subsystem lifecycles — https://dev.epicgames.com/documentation/en-us/unreal-engine/programming-subsystems-in-unreal-engine]

7.3 First-party sample persistence (Lyra) — set expectations correctly

[VERIFIED — https://dev.epicgames.com/documentation/en-us/unreal-engine/lyra-sample-game-in-unreal-engine ; https://x157.github.io/UE5/LyraStarterGame/]

Lyra does NOT ship a general save/persistence system for progression, quests, or world state. Lyra demonstrates modular gameplay (GameFeatures, Experiences, the Game Phase Subsystem, GAS, UI); developers are expected to build their own persistence layer on top. There is no first-party "quest-flag persistence" reference implementation to copy — a known gap, confirmed by the recurring "how do you save in Lyra" forum threads. The Lyra-adjacent subsystem worth studying is the Game Phase Subsystem (hierarchical gameplay-tag-driven phases) — conceptually close to a tag-driven state machine, though it's runtime phase logic, not persistence.

7.4 State Tree — current status & fit for "fork tables"

[VERIFIED — https://dev.epicgames.com/documentation/en-us/unreal-engine/overview-of-state-tree-in-unreal-engine ; https://dev.epicgames.com/documentation/unreal-engine/external-statetree-quickstart-guide]

7.5 Gameplay Ability System (GAS) tag-based state — fit

[VERIFIED — https://dev.epicgames.com/documentation/unreal-engine/API/Plugins/GameplayAbilities/UAbilitySystemComponent/AddLooseGameplayTag ; https://github.com/tranek/GASDocumentation]

UAbilitySystemComponent maintains a live FGameplayTagCountContainer (AddLooseGameplayTag/RemoveLooseGameplayTag/HasMatchingGameplayTag), and some narrative systems piggyback quest flags on this. But it's a poor fit as the primary worldstate store: GAS is heavyweight (attributes, effects, prediction/replication), loose tags are not auto-persisted (still need hand-serializing to a SaveGame), and tags are presence/count only — they model booleans well but not enums or integers (two of the three ws.* types here). Pulling in the whole GAS plugin just to hold narrative flags is over-engineering. Use GameplayTags as the key vocabulary; don't use GAS-the-system as the container. [INFERRED — grounded in verified GAS tag mechanics + the boolean-only limitation]

7.6 Recommended architecture for 39 typed ws.* keys + fork tables

[Clearly INFERRED architectural judgment, built on the verified pieces above — no Epic-cited reference architecture exists for this; validate with a spike before committing.]

A custom UWorldStateSubsystem : UGameInstanceSubsystem as the runtime authority, holding live state, backed by a DataTable-driven fork-rule evaluator, persisted through a dedicated USaveGame:

1. State store: TMap<FGameplayTag, FWorldStateValue> on the subsystem, FWorldStateValue a small tagged-union struct (an enum discriminator + bool/int/enum payload) so all three ws.* types live in one map. GameplayTags give a generated, canon-driven key vocabulary (Ws.Chapter12.MetCassius, etc.) from the §4.6 pipeline.

2. Fork tables → a DT_ForkRules DataTable (row struct FForkRule : FTableRowBase: condition key, comparator, condition value, target key, set value, chapter/scope). The subsystem exposes EvaluateForks(FGameplayTag Scope), reading matching rows and applying writes to the TMap. Fork rows stay the flat data they already are in the spine, imported by the same Target-4 pipeline — no re-authoring into a state machine.

3. Persistence: UWorldStateSaveGame : USaveGame with one serialized copy of the map, saved via AsyncSaveGameToSlot. Only the ws.* map needs saving (small), so saves stay cheap.

4. State Tree as a consumer, not the store: where a quest/NPC needs to *react* to ws.* over time, drive an External State Tree whose Enter Conditions read the subsystem's tags — using State Tree for what it's genuinely good at (runtime state/consequence) while fork tables remain data.

Why this over the alternatives: State Tree alone mismatches stateless rule rows (§7.4); GAS alone can't hold enums/ints and isn't auto-persisted (§7.5); scattering fields across actors fails the "many independently-tracked flags" requirement (§7.1). The subsystem+DataTable+SaveGame hybrid reuses the existing CSV/registry pipeline for the fork rules, survives level loads by construction, and keeps canon as flat git-diffable data.

7.7 Target 7 residual unknowns

---

8. Licensing / costs for a solo commercial game

8.1 Core royalty terms — the classic model still holds, with recent sweeteners

[VERIFIED via multiple corroborating sources quoting https://www.unrealengine.com/license and the EULA — Epic's own pages returned HTTP 403 to automated fetching, so figures are cross-checked via secondary sources rather than a direct fetch of the primary page]

Scope clarification [VERIFIED/INFERRED synthesis]: Epic's April-2025 pricing restructure introduced a per-seat subscription (~US $1,850/seat/year) — but that applies to non-game / "other industries" use (film/TV, animation, architecture, automotive, simulation) for entities over $1M annual revenue. For games, the royalty model applies, not the seat fee. A solo commercial *game* pays $0 up front and 5% only above $1M/product — don't let the "$1,850 per seat" figure (which also surfaces in MetaHuman coverage) confuse the game-licensing picture.

8.2 Distribution-platform differences — materially changes the math

[VERIFIED — https://www.unrealengine.com/en-US/blog/self-service-publishing-now-available-for-the-epic-games-store ; CG Channel; PocketGamer]

8.3 MetaHuman licensing — a major recent change

[VERIFIED — https://www.metahuman.com/license ; https://www.cgchannel.com/2025/06/you-can-now-sell-metahumans-or-use-them-in-unity-or-godot/ ; Creative Bloq; Epic forum "Licensing Changes to MetaHumans"]

8.4 EULA and AI-/procedurally-generated content — the highest-stakes finding in this section

[VERIFIED that these clauses exist, via search summaries quoting https://www.unrealengine.com/eula/unreal and /eula/content, plus https://forums.unrealengine.com/t/new-eula-ai-restriction/2068913 — the EULA pages themselves 403'd automated fetching, so exact section numbers are unconfirmed and should be pulled from a live browser session before this is treated as final legal guidance]

1. Restriction on using the Licensed Technology to train generative AI: "You must ensure that your activities with the Licensed Technology do not… result in using the Licensed Technology as a training input… [or prompt-based input] into any Generative AI Program." "Generative AI Program" is defined broadly (AI/ML/deep-learning/neural-nets generating audio, visual, or text content).

2. "NoAI" content: Fab/marketplace content can be tagged "NoAI"; users must not use NoAI content in datasets/development/inputs for Generative AI Programs. Epic commits not to feed Licensed Content into generative AI itself.

3. MetaHuman AI-training prohibition (§8.3).

Scope interpretation [INFERRED, flagged for legal confirmation]:

8.5 Target 8 residual unknowns

---

9. THE UE CHAIN, STEP BY STEP

This is the concrete, ordered list of what the autonomous pipeline feeds the engine, from this project's schema to a playable region. Each step gives artifact → format → API/mechanism, followed by its automation confidence and any flag. Steps 0-1 are one-time setup; Steps 2-12 repeat per region/chapter; Steps 13-14 are whole-project.

Pre-step (our side, not a UE question): spine extraction

Our site rows, boss phase→beat maps, scene rows, and fork tables currently live embedded in typed markdown inside the per-chapter story spine docs (§3b, §9, §13), not as standalone tables — only the registries (bosses, creatures, weapons, etc.) are already flat CSV. Before any of the UE-side steps below can run, a markdown-table-extraction step (our own tooling, not an Epic API) must pull the site/scene/fork rows out of the spine .md files into the same CSV/JSON shape as the registries. This is called out here for completeness, but it is not a UE research question — it doesn't appear in the residual-unknowns register below because it has nothing to do with Epic's documentation.

Step 0 — Schema codegen + compile (one-time, not per-region)

Step 1 — Registry ingestion → DataTables

Step 2 — World Partition region scaffolding

Step 3 — Terrain heightmap generation (external)

Step 4 — Landscape actor creation + heightmap import — the key engineering dependency

Step 5 — Landscape material auto-assignment

Step 6 — Data Layer tagging (protected/safe-zone flags)

Step 7 — PCG-driven population (flora/fauna/creatures/bosses/props)

Step 8 — Boss encounter gameplay wiring (§9 phase→beat maps) — flagged as outside the content pipeline

Step 9 — NPC / faction roster generation

Step 10 — Worldstate/save wiring (39 ws.* keys + fork tables)

Step 11 — Cinematic assembly (§13 scene rows)

Step 12 — Validation

Step 13 — Cook + package (per-region or full build)

A parallel/emerging path worth prototyping alongside the deterministic chain

UE 5.8's official, Experimental Unreal MCP plugin (Claude-named by Epic) can drive PCG graph authoring and general editor operations conversationally (§1.1 bonus finding, §3.6). Epic positions it as supervised/assistive, not a deterministic backbone. Recommendation: keep Steps 0-13 above as the pipeline's deterministic spine; use the MCP plugin for one-off template/graph authoring and iteration, not for the production run across all 69 regions, until it matures out of Experimental.

---

10. Consolidated residual-unknowns register

Every item below is something this research could not determine from public Epic documentation (or found only via community/secondary corroboration) — the true residual unknowns for human review, in one place.

#AreaUnknownWhy it matters
1Target 1Exact 5.8 PCGComponent/PCGGraph Python signatures not re-pinned this sessionPCG API churned through 5.7/5.8; verify before coding
2Target 1/remote/batch has a reported crash bugDon't depend on batched Remote Control calls without testing
3Target 1Headless commandlet flag spelling (-run=pythonscript, -ExecutePythonScript=) not re-confirmed against one specific 5.8 pageLow risk (stable community practice), but a 1-minute check is cheap insurance before CI wiring
4Target 2Whether the Landscape import dialog has a distinct "resolution calculator" beyond auto-populating fieldsMinor UX question, doesn't change the underlying size-table contract
5Target 2No documented way to procedurally paint layers on an *existing* landscape via PythonForces the auto-material-or-PCG-only approach for layer assignment
6Target 2/4Landscape heightmap import has no stock Python path at all — requires a C++ shim or third-party pluginThe single largest pure-engineering dependency in the terrain chain (Step 4)
7Target 3Exact ship-versions of PCG roadmap items (Attribute Set Tables, Native Level to PCG Data Asset, PCG Offline Builder)The shipping nodes already cover the core need; these are refinements, not blockers
8Target 3Community-reported edge-case bugs in PCGWorldPartitionBuilder (iterative cell loading + Grid Size node)Test against the specific template graphs before relying on it in CI
9Target 4Row-reference-survives-rename-iff-stable-RowName is a sound inference, not an Epic-quoted guaranteeReinforces the "never re-key a RowName" pipeline rule
10Target 4No official JSON→PrimaryDataAsset importer confirmed to existAffects only the DataAsset path, not the DataTable path this project will mostly use
11Target 5No published hard number for max simultaneous MetaHumans (VRAM/groom-bound)Affects how aggressively named-NPC MetaHumans can be used per scene
12Target 5Cloud auto-rig/texture-synthesis throughput/latency at "hundreds of characters" scale is undocumentedThe real risk to validate empirically before committing to MetaHuman-per-NPC generation at this project's roster size
13Target 5Whether the Experimental MetaHuman Crowd plugin is production-stable enough to ship a solo title onDetermines whether a classic modular-NPC fallback is needed for launch
14Target 6Exact call signatures for add_spawnable_from_class/instance, audio-track add_track, and channel keying not quoted verbatim from the one tutorial pageConfirm against the per-class Python API reference and shipped examples during implementation — low risk, native API members
15Target 6-RenderOffscreen/-NoLoadingScreen as fully-headless MRQ flags are community-standard, not quoted on the specific 5.8 doc pageLow risk, easy to test empirically
16Target 6The §13 scene-row schema has no camera-blocking, performance-content, or dialogue/audio fieldsDesign gap on our side, not a UE documentation gap — needs schema extension or a template/heuristic authoring layer
17Target 7No official Epic worldstate/save architecture for many typed flags exists; Lyra ships no save reference at allThe largest architecture-level unknown in this brief — §7.6's subsystem design is synthesized, not cited; spike it before committing
18Target 8Exact EULA section numbers for royalty and AI clauses unconfirmed (pages 403'd to automated fetch)A human should open the live EULA in a browser and capture exact section references before citing as legal fact
19Target 8The EULA's generative-AI "prompt-based input" clause scope is genuinely ambiguous, per Epic's own communityFlag for legal review before locking the pipeline architecture — see §8.4 for the safe-design interpretation in the meantime
20Target 9 (chain)Boss phase→beat maps translating into actual multi-phase fight AI logic has no UE-documentation answer at allThis is a game-code design problem, comparable in scope to the landscape C++ shim, not a pipeline-wiring problem

---

Source index (all URLs cited above, deduplicated)

Generated by harness/site/structure_site.py — the URL path is the repo path. review root