BPVM Snack Pack #10 - The Function Factory: Where Graphs Become Functions
Your Event Graph isn't really a graph when it runs. It's transformed into a giant function called the Ubergraph. Here's how the function factory works its magic.
TL;DR — The Blueprint compiler merges all Event Graph pages into a single Ubergraph function, where each event like BeginPlay or Tick becomes just an entry-point stub. Regular, generated, and interface function graphs are each processed into their own functions, macros expand inline and vanish, and every function gets an FKismetFunctionContext holding its terminals, execution order, and generated statements.
The content in this post is based on Unreal Engine 5.6.0
BPVM Snack Pack - Quick Blueprint knowledge drops! Part of the Blueprint to Bytecode series.
The Multiple Graph Problem
You’ve created multiple Event Graph pages for organization:
- “Player Input” page
- “Combat Logic” page
- “UI Updates” page
Clean and organized, right? But here’s the secret: They all become ONE function.
Meet the Ubergraph
The compiler takes ALL your event graphs and merges them:
1
2
3
4
5
6
7
8
9
10
11
12
void CreateAndProcessUbergraph()
{
// Create one mega-graph
ConsolidatedEventGraph = NewObject<UEdGraph>("Ubergraph");
// Copy ALL event graph pages into it
for (UEdGraph* EventGraph : Blueprint->EventGraphs) {
MergeIntoUbergraph(EventGraph, ConsolidatedEventGraph);
}
// This is now ONE giant function!
}
Think of it like taking multiple recipe cards and combining them into one cookbook!
Why Merge Everything?
The VM doesn’t understand “pages” - it only executes functions:
1
2
3
4
5
6
7
8
9
10
11
// What you see in editor:
EventGraph_Page1 → BeginPlay node
EventGraph_Page2 → Tick node
EventGraph_Page3 → OnDamaged node
// What the VM sees:
Ubergraph() {
BeginPlay_Implementation();
Tick_Implementation();
OnDamaged_Implementation();
}
Pages are for humans. The machine wants one function.
The Function Creation Pipeline
The factory processes four types of graphs:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void CreateFunctionList()
{
// 1. The Ubergraph (all event graphs merged)
if (DoesSupportEventGraphs(Blueprint)) {
CreateAndProcessUbergraph();
}
// 2. Regular function graphs
for (UEdGraph* Graph : Blueprint->FunctionGraphs) {
ProcessOneFunctionGraph(Graph);
}
// 3. Generated function graphs (from macros, etc.)
for (UEdGraph* Graph : GeneratedFunctionGraphs) {
ProcessOneFunctionGraph(Graph);
}
// 4. Interface functions
for (auto& Interface : Blueprint->ImplementedInterfaces) {
for (UEdGraph* Graph : Interface.Graphs) {
ProcessOneFunctionGraph(Graph);
}
}
}
Processing Each Function
Each graph goes through the same factory process:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void ProcessOneFunctionGraph(UEdGraph* SourceGraph)
{
// Step 1: Clone to temporary graph
UEdGraph* TempGraph = DuplicateGraph(SourceGraph);
// Step 2: Expand nodes (macros become real nodes)
ExpandAllMacroNodes(TempGraph);
// Step 3: Create function context
FKismetFunctionContext* Context = CreateFunctionContext();
Context->SourceGraph = TempGraph;
// Step 4: Add to function list
FunctionList.Add(Context);
}
The Event Node Magic
Each event in your graph becomes a function stub:
1
2
3
4
5
6
7
8
// You have a BeginPlay event node
UK2Node_Event* BeginPlayNode;
// Compiler creates a function stub
void ReceiveBeginPlay() {
// Jump to the right spot in Ubergraph
Ubergraph(ENTRY_BeginPlay);
}
Events are just entry points into the mega-function!
Function Context: The Blueprint
Each function gets a FKismetFunctionContext:
1
2
3
4
5
6
7
8
struct FKismetFunctionContext
{
UEdGraph* SourceGraph; // The visual graph
TArray<FBPTerminal*> Parameters; // Input pins
TArray<FBPTerminal*> Locals; // Local variables
TArray<UEdGraphNode*> LinearExecutionList; // Node order
TArray<FBlueprintCompiledStatement*> AllGeneratedStatements; // The code!
};
This context is the blueprint (pun intended) for building the actual function!
Macro Expansion
Macros get inlined during processing:
1
2
3
4
5
// Before expansion
CallMacro("MyUtilityMacro")
// After expansion (nodes copied directly)
Node1 → Node2 → Node3 → Node4 // The macro's actual nodes
Macros disappear - their nodes are copied right into your function!
The Ubergraph Name
Ever see this in crash logs?
1
ExecuteUbergraph_BP_MyActor
Now you know what it means - it’s the mega-function containing all your events!
Function Types Explained
Regular Functions:
1
2
ProcessOneFunctionGraph(MyFunction)
→ Creates: MyFunction()
Event Graph Events:
1
2
3
CreateAndProcessUbergraph()
→ Creates: ExecuteUbergraph_BP_MyActor()
→ With stubs: ReceiveBeginPlay(), ReceiveTick(), etc.
Interface Functions:
1
2
ProcessOneFunctionGraph(InterfaceFunc)
→ Creates: InterfaceFunc_Implementation()
The Hidden Optimization
Why merge everything into Ubergraph?
Without Ubergraph (inefficient):
1
2
3
4
void BeginPlay() { /* bytecode */ }
void Tick() { /* bytecode */ }
void OnDamaged() { /* bytecode */ }
// Three separate function calls, three contexts
With Ubergraph (optimized):
1
2
3
4
5
6
7
8
void ExecuteUbergraph(int EntryPoint) {
switch(EntryPoint) {
case 0: /* BeginPlay bytecode */
case 1: /* Tick bytecode */
case 2: /* OnDamaged bytecode */
}
// One function, shared context!
}
Quick Takeaway
- All Event Graph pages become ONE function (the Ubergraph)
- Regular functions each get their own function
- Macros are expanded inline (they disappear)
- Each function gets a FKismetFunctionContext (its blueprint)
- Events are just entry points into the Ubergraph
- Interface functions get _Implementation suffix
The Factory Never Sleeps
Every time you compile:
- Event graphs merge into Ubergraph
- Functions are processed individually
- Macros expand and vanish
- Contexts are created for each function
- The factory produces executable functions!
Want More Details?
For the complete function creation process:
Next: How everything gets linked together!
🍿 BPVM Snack Pack Series
- ← #9: Variables Become Properties
- #10: The Function Factory ← You are here
- #11: Linking and Binding →
Cite this post
Jayden Zhang. “BPVM Snack Pack #10 - The Function Factory: Where Graphs Become Functions.” Jayden Zhang’s Blog, October 28, 2025. https://www.jaydengames.com/posts/bpvm-snack-10-function-factory/
BibTeX
@misc{bpvm-snack-10-function-factory2025,
author = {Jayden Zhang},
title = {BPVM Snack Pack #10 - The Function Factory: Where Graphs Become Functions},
year = {2025},
url = {https://www.jaydengames.com/posts/bpvm-snack-10-function-factory/},
note = {Jayden Zhang’s Blog}
}