BPVM Snack Pack #2 - The Graph System Decoded
The node graph you see is actually two systems: the data (UEdGraph) and the rendering (Slate). Here's why that separation matters.
The content in this post is based on Unreal Engine 5.4.0
BPVM Snack Pack is a companion series to the deep-dive Blueprint to Bytecode series. Each snack is a quick 3-5 minute read. Grab your coffee!
Model-View Separation (The Unreal Way)
When you open a Blueprint and see this node graph:
You’re looking at classic MVC architecture in action:
- The Model (
UEdGraph- The data structure) - The View (
SGraphEditor- The Slate rendering)
The Data Layer: UEdGraph
The graph data is stored in a UEdGraph object. Think of it as a JSON structure that describes:
- What nodes exist
- What they’re connected to
- What values they have
1
2
3
4
5
class UEdGraph
{
TArray<UEdGraphNode*> Nodes; // All your nodes
// That's basically it for the core!
};
No rendering code. No UI. Just pure data.
The Visual Layer: SGraphEditor
When you see the pretty graph on screen, that’s a Slate widget called SGraphEditor. It:
- Reads the
UEdGraphdata - Draws the boxes and lines
- Handles your mouse clicks
- Updates the
UEdGraphwhen you change things
Important: The graph can exist without any visuals! When you package your game, the UEdGraph is compiled to bytecode and the visual layer is stripped out. Your shipped game only contains the executable code, not the pretty node editor.
Nodes: Data Meets Logic
Each node is a UEdGraphNode object (or more specifically, UK2Node for Blueprint):
1
2
3
4
5
6
class UEdGraphNode
{
TArray<UEdGraphPin*> Pins; // Input/output connections
FString NodeComment; // That yellow note you can add
// Node-specific data here
};
And yes, it also has a visual representation: SGraphNode (another Slate widget).
Pins: The Connection Points
Pins are where the magic happens:
1
2
3
4
5
6
7
class UEdGraphPin
{
FName PinName; // "Target", "Return Value", etc.
EPinDirection Direction; // Input or Output?
TArray<UEdGraphPin*> LinkedTo; // What's connected to me?
FString DefaultValue; // Value if nothing connected
};
When you drag a wire between nodes, you’re creating a LinkedTo relationship between two pins.
The Rulebook: Schema
You can’t connect an Integer pin to a String pin. That’s the UEdGraphSchema enforcing type safety:
1
2
3
4
5
6
7
class UEdGraphSchema
{
// Defines rules:
// - What nodes are allowed?
// - What connections are valid?
// - What shows up in the right-click menu?
};
Different graph types have different schemas:
- Blueprint uses
UEdGraphSchema_K2 - Animation Blueprint uses
UAnimationGraphSchema - Behavior Tree uses
UBehaviorTreeGraphSchema
Each enforces its own rules!
Why This Separation Matters
Data is cheap to store and compile:
1
2
3
// Easy to save, load, and process
UEdGraph* Graph = LoadGraphFromAsset();
CompileToByteCode(Graph);
Visuals are expensive:
1
2
3
// Only create when editor is open
SGraphEditor* VisualGraph = CreateWidget();
VisualGraph->SetGraphToVisualize(Graph);
At runtime, your game never loads the visual layer. It only cares about the compiled bytecode!
Quick Takeaway
- UEdGraph = Your node data (serialized in .uasset)
- UEdGraphNode = Individual node data (Print String, Branch, etc.)
- UEdGraphPin = Connection points with type information
- SGraphEditor / SGraphNode = The pretty visuals (editor-only)
- UEdGraphSchema = The rulebook (what’s allowed?)
Want More Details?
For the complete breakdown of all these systems:
Next snack: How those nodes turn into executable code!
🍿 BPVM Snack Pack Series
- ← #1: What is a Blueprint, Really?
- #2: The Graph System Decoded ← You are here
- #3: Compilation Kick-Off →

