Type: research
Generating new M.A.M. research trees from YAML, registering existing ones, and how this fits alongside schematics and recipes.
This entry type runs at the Research stage, after Schematics. It does not support
live-reload, so changes require a restart. Its entries key is research, and the default
parent is /Script/FactoryGame.FGResearchTree. The required base class is the same,
/Script/FactoryGame.FGResearchTree (or a subclass). Register-only mode via class: is
supported here too, with the same duality as recipe/schematic.
research (or its filename-convention alias mam, for example my-tree.mam.yml) generates or
registers UFGResearchTree-derived classes: the individual M.A.M. (Molecular Analysis Machine)
research trees themselves, not the schematics nested inside them. Like
Recipes, it supports two modes. You can generate a
brand-new tree with id:, or register an existing one untouched except for a property tweak with
class:. The mode-selection mechanics are identical to recipe, so see that page’s “register an
existing class” section if you need the general rules. This page only covers what’s specific to
trees.
Editing an existing research tree
Section titled “Editing an existing research tree”Most of the time you don’t need to generate a research tree. The base game’s trees already
exist, and you just want to rename or retune one. That’s register-only mode, or honestly, just a
plain cdo patch: both work identically for editing something that already exists. Here’s an
example renaming the Mycelia tree’s display text:
type: cdopatches: - target: /Game/FactoryGame/Schematics/Research/Mycelia_RS/ResearchTree_Mycelia.ResearchTree_Mycelia_C properties: - path: mDisplayName value: 'Mycelia (Rebalanced)'Generating a new research tree
Section titled “Generating a new research tree”Use type: research with id: when you actually want a new tree. This applies when your
pack adds a whole new content line that deserves its own M.A.M. entry, rather than living inside
an existing tree. mDisplayName is the tree’s name in the menu, and mMenuPriority controls
where it sorts relative to other trees:
type: researchresearch: - id: MyContentLineTree properties: - path: mDisplayName value: My Content Line - path: mMenuPriority value: 50register: true (default) queues it into SML’s UModContentRegistry per-world before the freeze,
same mechanism as recipes and schematics.
Gating tree unlock and visibility
Section titled “Gating tree unlock and visibility”Research entries accept two instanced FGAvailabilityDependency lists:
unlockDependencies:appends tomUnlockDependencies;visibilityDependencies:appends tomVisibilityDependencies.
type: researchresearch: - id: MyContentLineTree unlockDependencies: - class: /Script/FactoryGame.FGSchematicPurchasedDependency properties: - path: mSchematics value: - Schematic_MyPrerequisite visibilityDependencies: - class: /Game/FactoryGame/AvailabilityDependencies/BP_GamePhaseReachedDependency.BP_GamePhaseReachedDependency_C properties: - path: mGamePhase value: EGP_EarlyGameNative and Blueprint paths both work. Known native classes automatically remap to concrete Blueprint implementations. Full inventory: Availability Dependency Classes.
⚠️ A schematic does not “point at” a tree. Unlike
mProducedIn/mProducton a recipe, there is no field onUFGSchematicthat associates it with a research tree. The relationship works the other way around: the tree’smNodesarray visually places schematics inside it.
Adding and removing visual nodes
Section titled “Adding and removing visual nodes”Node mutation lives directly on each research: entry. addNodes: is additive: it appends real
BPD_ResearchTreeNode instances and does not replace an existing node implicitly. Each useful node
names a schematic: and a coordinate:; it can also define parents:, nodesToUnhide:,
unhiddenBy:, and optional properties:. A graph reference may be a literal coordinate or another
node’s schematic class.
References work both for nodes in the same list, regardless of their order, and for nodes that are
already present in the tree. This example adds one node to the vanilla Mycelia tree without
re-registering that existing tree:
research: - class: /Game/FactoryGame/Schematics/Research/Mycelia_RS/ResearchTree_Mycelia.ResearchTree_Mycelia_C register: false autoPath: true addNodes: - schematic: Schematic_MyExtension coordinate: X: 4 Y: 2 parents: - schematic: Schematic_ExistingParent nodesToUnhide: - X: 5 Y: 2For a concrete base-game example, this adds the Pure Super Ingot schematic after the Mycelia Gas Mask research node:
type: researchresearch: - class: /Game/FactoryGame/Schematics/Research/BPD_ResearchTree_Mycelia.BPD_ResearchTree_Mycelia_C register: false autoPath: true addNodes: - schematic: Schematic_PureSuperIngot coordinate: X: 4 Y: 6 parents: - schematic: /Game/FactoryGame/Schematics/Research/Mycelia_RS/Research_Mycelia_GasMask.Research_Mycelia_GasMask_CWith autoPath: true, KDataForge turns every resolved parents: edge from addNodes: into a
matching straight road on the parent. For custom or bent roads, use autoPath: false with
childrenAndRoads:; a parent can provide one block map with key and points fields or a sequence of them for
multiple children. Set class: on a node only when a custom UFGResearchTreeNode subclass is
required. Its ordinary properties: list remains available, but convenience fields that the
subclass does not expose are
reported and skipped rather than failing the whole document.
To remove a node, select it by schematic class with tree-entry-level removeNodes:. It accepts a
scalar class reference or a block map with schematic:. KDataForge applies removals before addNodes:
additions in the same tree entry, then removes the node and all surviving Parents,
NodesToUnhide, UnhiddenBy, and ChildrenAndRoads references to its coordinate. addNodes: then
appends replacements or unrelated new nodes. autoPath: true applies to those additions and writes
straight roads from every resolved parent:
research: - class: /Game/FactoryGame/Schematics/Research/Mycelia_RS/ResearchTree_Mycelia.ResearchTree_Mycelia_C autoPath: true removeNodes: - Schematic_ObsoleteExtension addNodes: - schematic: Schematic_NewExtension coordinate: X: 6 Y: 3 parents: - schematic: Schematic_ExistingParentFor a move or replacement, use the same schematic in removeNodes: and addNodes: with its new
coordinate. Removal still happens first, so duplicate nodes and stale roads are not retained.
nodes: remains a legacy alias. When both keys are present, addNodes: wins and KDataForge warns
that nodes: was ignored. autoPath: works with addNodes: and legacy nodes:.
Removing research trees
Section titled “Removing research trees”A type: research document accepts a top-level remove: sequence. type: mam is an alias for
research, so it accepts the same removal grammar. Each entry is either a bare class reference (a
full Unreal class path, a bare loaded class name, or a generated content id from this or another
loaded KDataForge pack) or a filter map that removes every tree passing the
scope filters
(matchName:, matchTag:, where:; the scope defaults to FGResearchTree). Removal-only
documents are valid, and remove: can also be mixed with normal research: entries:
type: researchremove: - /Game/FactoryGame/Schematics/Research/BPD_ResearchTree_Caterium.BPD_ResearchTree_Caterium_C - MyGeneratedResearchTree - matchName: /Game/SomeMod/Research/* # every tree another mod ships, by folderA bare reference names the exact research-tree class to remove; it does not remove subclasses. If
a generated id is ambiguous across packs, KDataForge logs the same ambiguity diagnostic used for
other short-id class references. Removals run after registrations, so an explicit remove: wins
over a register: for the same class. The consolidated guide is
Removing Content.
Research-tree removal is save-clean. KDataForge removes the class from SML’s content registry before the M.A.M. builds its per-session tree list, so uninstalling the pack brings the tree back on the next load.
Removal does not revoke progress. Already-unlocked or completed research state stays in the save,
and any unlocks already granted by that progress stay granted. This only removes the tree from the
current available research-tree list while the pack is installed. To remove recipes granted through
that progression, also use recipe remove:.
Troubleshooting
Section titled “Troubleshooting”- New tree doesn’t appear in the M.A.M. menu: confirm registration succeeded
(
/kdf report). An empty tree with no nodes may also simply not render meaningfully in the M.A.M. UI, so see the callout above and the linked tutorial for what’s currently achievable. - Just want to rename or reprioritise a vanilla tree: don’t generate anything. Use a plain
cdopatch as shown above. It’s simpler and doesn’t touch the content registry at all. - Want a schematic unlocked through research instead of the HUB: that’s just
mType: EST_MAMon an ordinary Type: schematic entry. Nothing tree-specific about it.
