G3Engine’s Visual Scripting system lets you create complex game logic without writing code. Using a Blueprint-style node graph, you can connect events to actions, add conditional logic, and integrate Web3 features visually.
Overview
The Node Editor is powered by React Flow and provides a professional node-based programming interface similar to Unreal Engine’s Blueprints.
Visual scripts compile to executable callbacks that run in your game’s main loop.
Node Graph Interface
The node editor provides a full-featured graph editing experience:
Navigation Controls
Pan : Click and drag the background
Zoom : Scroll wheel to zoom in/out
Fit View : Automatically frame all nodes
Snap to Grid : 16x16 pixel grid for clean layouts
Visual Features
Background
MiniMap
Controls
Dotted grid background with configurable spacing and subtle coloring: < Background
variant = {BackgroundVariant. Dots }
gap = { 20 }
size = { 1 }
color = "rgba(255,255,255,0.04)"
/>
Bird’s-eye view of entire graph in bottom-right corner:
Node colors match category
Current viewport highlighted
Click to jump to areas
Zoom controls in bottom-left:
Zoom in/out buttons
Fit view button
Interactive zoom slider
Node Anatomy
Every node follows a consistent Blueprint-style structure:
interface BlueprintNodeData {
label : string ; // Node title
category : string ; // Color theme (event, action, logic, etc.)
icon : string ; // Emoji icon
description : string ; // Tooltip text
inputs : PinDef []; // Left-side input pins
outputs : PinDef []; // Right-side output pins
compact ?: boolean ; // Condensed layout for utility nodes
}
Pin System
Nodes connect via typed pins (handles):
interface PinDef {
id : string ; // Unique identifier
label : string ; // Display name
type : string ; // Data type (exec, boolean, float, int, string, vector, object)
}
Pin Types & Colors
Type Color Shape Usage execWhite Square Execution flow booleanRed Circle True/false values floatGreen Circle Decimal numbers intCyan Circle Whole numbers stringPink Circle Text data vectorYellow Circle Position/direction (x,y,z) objectBlue Circle Game object references anyGray Circle Accepts any type
// Pin colors from NodeEditor.tsx:26-34
const pinColors : Record < string , string > = {
exec: '#ffffff' ,
boolean: '#cc0000' ,
float: '#00cc88' ,
int: '#06b6d4' ,
string: '#f472b6' ,
vector: '#eab308' ,
object: '#3b82f6' ,
any: '#9ca3af' ,
};
Execution pins use square shapes to visually distinguish control flow from data flow.
Node Categories
Nodes are organized into color-coded categories:
Events (Red)
Trigger points for game logic:
Event Begin Play
Event Tick
On Key Press
On Collision
On Click
Fires once when the game starts. Outputs: {
label : 'Event Begin Play' ,
category : 'event' ,
icon : '⚡' ,
outputs : [{ id: 'exec-out' , label: '' , type: 'exec' }]
}
Fires every frame. Outputs:
Exec (white square)
Delta Time (float) - Seconds since last frame
Use for continuous updates like movement, animations, timers. Fires when a keyboard key is pressed. Outputs:
Exec (white square)
Key (string) - Which key was pressed
Perfect for player input handling. Fires when two physics objects collide. Outputs:
Exec (white square)
Other Object (object) - What we collided with
Essential for hit detection, pickup collection. Fires when an object is clicked. Outputs:
Exec (white square)
Position (vector) - World position of click
Great for UI buttons, interactive objects.
Actions (Blue)
Operations that affect the game world:
Move To
Rotate
Spawn Object
Play Sound
Move an object to a target position. Inputs:
Exec In
Target (object)
Position (vector)
Speed (float)
Outputs:
Exec Out - Continues immediately
Done - Fires when movement completes
Rotate an object by degrees. Inputs:
Exec In
Target (object)
Degrees (float)
Outputs: Create a new object in the scene. Inputs:
Exec In
Type (string) - Object type to spawn
Position (vector)
Outputs:
Exec Out
Object (object) - Reference to spawned object
Play an audio clip. Inputs:
Exec In
Sound (string) - Audio file path
Volume (float) - 0.0 to 1.0
Outputs:
Logic (Gray)
Control flow and conditionals:
If/Else conditional. Inputs:
Exec In
Condition (boolean)
Outputs:
True - Executes if condition is true
False - Executes if condition is false
// Example: Check if player has key before opening door
[ Has Key ? ] → [ Branch ] → True → [ Open Door ]
→ False → [ Play Locked Sound ]
Execute multiple actions in order. Inputs: Outputs:
Then 0 - Executes first
Then 1 - Executes second
Then 2 - Executes third
Repeat an action N times. Inputs:
Exec In
Count (int) - Number of iterations
Outputs:
Loop Body - Executes each iteration
Index (int) - Current iteration (0 to Count-1)
Completed - Fires after all iterations
Flow Control (Cyan)
Wait for a duration before continuing. Inputs: Outputs:
Completed - Fires after delay
Perfect for timed events, cooldowns, delayed responses.
Math (Yellow)
Mathematical operations and comparisons:
Add
Multiply
Compare
Random Float
Add two numbers. Inputs: A (float), B (float)Outputs: Result (float)
Multiply two numbers. Inputs: A (float), B (float)Outputs: Result (float)
Compare two values. Inputs: A (float), B (float)Outputs:
A > B (boolean)
A = B (boolean)
A < B (boolean)
Generate random number in range. Inputs: Min (float), Max (float)Outputs: Value (float)
Variables (Green)
Data getters and setters:
// Get Position node - compact layout
{
label : 'Get Position' ,
category : 'variable' ,
icon : '📍' ,
inputs : [{ id: 'target' , label: 'Target' , type: 'object' }],
outputs : [{ id: 'position' , label: 'Position' , type: 'vector' }],
compact : true
}
Web3 Nodes (Purple)
Blockchain integration nodes for Solana and Pump.fun:
Token Operations
🚀 Launch Token
💰 Buy Token
💸 Sell Token
Launch a token on Pump.fun bonding curve. Inputs:
Exec In
Name (string)
Symbol (string)
Image URI (string)
Outputs:
Exec Out
Token Mint (string)
Tx Hash (string)
Buy tokens on Pump.fun. Inputs:
Exec In
Token Mint (string)
SOL Amount (float)
Slippage % (float)
Outputs:
Exec Out
Tokens Received (float)
Tx Hash (string)
Sell tokens on Pump.fun. Inputs:
Exec In
Token Mint (string)
Token Amount (float)
Slippage % (float)
Outputs:
Exec Out
SOL Received (float)
Tx Hash (string)
NFT Operations
Create an NFT from a game asset. Inputs:
Exec In
Name (string)
Image URI (string)
Attributes (object)
Outputs:
Exec Out
Mint Address (string)
Tx Hash (string)
Token Gating
Check if player holds enough tokens. Inputs:
Exec In
Token Mint (string)
Min Balance (float)
Outputs:
Has Access - Executes if balance >= min
No Access - Executes if balance < min
Balance (float) - Actual balance
Perfect for premium content, VIP areas, token-gated features.
Utility Nodes
💎 Check Balance
📊 Get Token Price
🎁 Reward Player
Get token/SOL balance (compact node). Inputs: Token Mint (string)Outputs: Balance (float)
Query Pump.fun bonding curve price. Inputs: Token Mint (string)Outputs:
Price in SOL (float)
Market Cap (float)
Give tokens as game reward. Inputs:
Exec In
Token Mint (string)
Amount (float)
Outputs:
Exec Out
Tx Hash (string)
Creating Connections
Connect nodes by dragging from output pins to input pins:
Click Output Pin
Click and hold on any output pin (right side of node).
Drag to Input
Drag the connection line to a compatible input pin (left side of target node).
Release
Release mouse to create connection. The edge animates and inherits the pin’s color.
// Connection handler from NodeEditor.tsx:758-780
const onConnect = useCallback (( params : Connection ) => {
// Determine edge color from pin type
const sourceNode = nodes . find ( n => n . id === params . source );
let strokeColor = '#5a5f6d' ;
if ( sourceNode ) {
const data = sourceNode . data as BlueprintNodeData ;
const pin = data . outputs . find ( o => o . id === params . sourceHandle );
if ( pin ) strokeColor = pinColors [ pin . type ] || '#5a5f6d' ;
}
setEdges (( eds ) => addEdge ({
... params ,
animated: true ,
style: { stroke: strokeColor , strokeWidth: 2 },
type: 'default' ,
}, eds ));
}, [ setEdges , nodes ]);
Edge colors automatically match the source pin type for easy visual tracing.
Adding Nodes
Add nodes to your graph via the palette:
Open Palette
Click ”➕ Add Node” button in top-left corner.
Search or Browse
Type in search box to filter
Click category tabs (Events, Actions, Logic, Math, Web3)
Select Node
Click any node template to add it to the graph.
The node palette shows:
Icon - Visual category indicator
Node name - In category color
Description - What the node does
// Palette categories from NodeEditor.tsx:737-745
const PALETTE_CATS = [ 'All' , 'Events' , 'Actions' , 'Logic' , 'Math' , 'Web3' ];
const PALETTE_CAT_MAP : Record < string , string []> = {
All: [],
Events: [ 'event' ],
Actions: [ 'action' ],
Logic: [ 'logic' , 'flow' ],
Math: [ 'math' , 'variable' ],
Web3: [ 'web3' ],
};
Script Compilation
Visual scripts compile to executable game logic:
interface CompiledAction {
eventType : string ; // keyPress, click, start, update, walletConnect
eventLabel : string ; // Human-readable event name
actionType : string ; // moveCharacter, playSound, mintNFT, etc.
actionLabel : string ; // Human-readable action name
params : Record < string , unknown >; // Node-specific parameters
}
interface CompiledScript {
actions : CompiledAction [];
}
Compilation Process
Graph Traversal
The compiler walks all edges connecting nodes: for ( const edge of edges ) {
const source = nodeMap . get ( edge . source );
const target = nodeMap . get ( edge . target );
// Pair source events with target actions
}
Type Detection
Node labels are analyzed to determine event and action types: if ( label . includes ( 'key' ) || label . includes ( 'wasd' ))
eventType = 'keyPress' ;
else if ( label . includes ( 'click' ))
eventType = 'click' ;
Action Pairing
Each edge creates a compiled action pairing an event with a response.
Callback Generation
Compiled actions generate executable callbacks for the game loop.
// From scriptCompiler.ts:29-85
export function compileGraph ( nodes : Node [], edges : Edge []) : CompiledScript {
const actions : CompiledAction [] = [];
for ( const edge of edges ) {
const source = nodeMap . get ( edge . source );
const target = nodeMap . get ( edge . target );
// Determine event and action types from labels
let eventType = 'unknown' ;
let actionType = 'unknown' ;
// ... type detection logic ...
actions . push ({
eventType ,
eventLabel: String (( source . data as any )?. label || source . id ),
actionType ,
actionLabel: String (( target . data as any )?. label || target . id ),
params: {},
});
}
return { actions };
}
Example Workflows
Basic Movement
[On Key Press] ──exec──> [Move To]
│ ↑
└─── key ──> [Get Player Position]
Collision Response
[On Collision] ──exec──> [Branch]
│ ├─ true ──> [Play Sound] ──> [Destroy]
└─ other ──> └─ false ──> [Bounce Back]
[Is Enemy?]
Token-Gated Content
[On Click Door] ──exec──> [Token Gate]
├─ Has Access ──> [Open Door] ──> [Play Animation]
└─ No Access ──> [Print "Locked"] ──> [Play Error Sound]
NFT Reward System
[Event Begin Play] ──exec──> [Check Balance: GameToken]
│
└─ balance ──> [Compare > 1000]
│
└─ A > B ──> [Branch]
└─ true ──> [Mint NFT]
Best Practices
Organization
Performance
Debugging
Group related nodes together
Use vertical space for parallel branches
Keep execution flow left-to-right
Add comments with Print String nodes
Avoid connecting to Event Tick unless necessary
Use Delay nodes instead of rapid polling
Cache object references in variables
Limit For Loop iterations in real-time contexts
Use Print String to log values
Test branches with both True and False paths
Verify Web3 nodes on devnet first
Check browser console for compiled script output
Web3 nodes require a connected wallet to execute. Test on Solana devnet before mainnet deployment.
Next Steps
Web3 Integration Deep dive into blockchain nodes and token economy
3D Editor Create objects to script in the 3D viewport
2D Editor Script 2D sprite behaviors and interactions
Asset Library Reference objects in your scripts