PCGIR
A PCG graph in Unreal is a binary procedural-generation network — sampler and filter nodes, each carrying its own settings, wired pin to pin, plus the auto-created input and output terminals — that you can only really read by opening the PCG editor and tracing edges across the canvas. PCGIR decompiles that same graph into one compact, line-based text document: every node with its settings class and edited properties, every connection, and the graph terminals, all written out as text you can diff, review, and hand to your assistant as context. PCGIR is read-only — it is how you read a PCG graph as text; compiling text back into an asset is a planned follow-up.
Why it matters
Diffable in version control
The same decompiler writes a pcgir.txt asset-dump sidecar next to the asset, so a tuned scatter density or a rewired filter shows up as a handful of changed text lines that git log -p and grep can read — instead of an opaque binary .uasset a reviewer has to open the editor to inspect.
Reviewable like code
You read the graph top to bottom in plain text: which node runs which settings class, what each edited property resolves to, and how the pins connect from input terminal to output. No clicking node to node across the canvas to reconstruct what the graph actually builds.
Context an AI can actually read
One consistent text language for the whole graph, with each node named by its qualified UPCGSettings class path and subgraph references surfaced inline as a subgraph = "…" property. Your assistant reads the graph as text and reasons about it, instead of being blind to a binary node network.
Faithful and deterministic
The pcg.decompile RPC and the pcgir.txt sidecar share one decompiler path, so the file on disk and the live decompile stay in lockstep. The walk explicitly merges the input/output terminals that live outside GetNodes() and traverses output pins only, so each edge emits exactly once.
A taste
An entry pcg block names its target graph as a backtick-delimited path. Each node
binds a sequential name to a settings class path, an optional @(x, y) gives layout, edited
properties sit in braces, and connect lines wire source output pins to destination input
pins — including the reserved N_Input / N_Output terminals:
entry pcg `/Game/PCG/G_FoliageScatter` {
node N_Input = `/Script/PCG.PCGGraphInputOutputSettings` @(-400, 0)
node N_Output = `/Script/PCG.PCGGraphInputOutputSettings` @(800, 0)
node N1 = `/Script/PCG.PCGSurfaceSamplerSettings` @(0, 0) {
PointsPerSquaredMeter = 2.5
}
node N2 = `/Script/PCG.PCGSubgraphSettings` @(400, 0) {
subgraph = "/Game/PCG/SG_BoulderScatter"
}
connect N_Input.In -> N1.In
connect N1.Out -> N2.In
connect N2.Out -> N_Output.Out
}
Subgraph nodes are flattened, not recursed: the referenced graph's path is emitted as a
subgraph = "…" property on the parent node, and you decompile the child separately by its own
asset path. Per-node names (N1, N2, …) follow GetNodes() order and
are stable within a single decompile, but they are not asset-stable — re-decompiling after an edit
can renumber them.
How your assistant uses it
Your assistant decompiles the asset to PCGIR with pcg.decompile and reads it for context
— to answer questions about the graph or to plan edits it then applies through the individual
pcg.* edit RPCs. This IR is read-only; it does not write the asset back.
You: What's scattering points in G_FoliageScatter, and does it call a subgraph?
call("pcg.decompile", {assetPath:"/Game/PCG/G_FoliageScatter"})
→ {text:"entry pcg `/Game/PCG/G_FoliageScatter` {\n node N1 = `/Script/PCG.PCGSurfaceSamplerSettings` @(0,0) {\n PointsPerSquaredMeter = 2.5\n }\n node N2 = `/Script/PCG.PCGSubgraphSettings` @(400,0) {\n subgraph = \"/Game/PCG/SG_BoulderScatter\"\n }\n ...\n}",
warnings:[]}
G_FoliageScatter scatters with a Surface Sampler at 2.5 points/m², then feeds a
Subgraph node that calls out to /Game/PCG/SG_BoulderScatter.
pcg.* RPCs, not by writing PCGIR. Decompile always flattens subgraphs — the
includeReferencedSubgraphs flag is reserved for that future direction and only surfaces a
warning today. And like the other PinWright IRs, a decompile preserves graph structure (nodes, edges,
settings values, positions), not editor cosmetics such as comment boxes, node colors, or editor list order.