Skip to main content
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:
  • 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

Dotted grid background with configurable spacing and subtle coloring:
<Background
  variant={BackgroundVariant.Dots}
  gap={20}
  size={1}
  color="rgba(255,255,255,0.04)"
/>

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

TypeColorShapeUsage
execWhiteSquareExecution flow
booleanRedCircleTrue/false values
floatGreenCircleDecimal numbers
intCyanCircleWhole numbers
stringPinkCircleText data
vectorYellowCirclePosition/direction (x,y,z)
objectBlueCircleGame object references
anyGrayCircleAccepts 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:
Fires once when the game starts.Outputs:
  • Exec (white square)
{
  label: 'Event Begin Play',
  category: 'event',
  icon: '⚡',
  outputs: [{ id: 'exec-out', label: '', type: 'exec' }]
}

Actions (Blue)

Operations that affect the game world:
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

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]

Flow Control (Cyan)

Wait for a duration before continuing.Inputs:
  • Exec In
  • Seconds (float)
Outputs:
  • Completed - Fires after delay
Perfect for timed events, cooldowns, delayed responses.

Math (Yellow)

Mathematical operations and comparisons:
Add two numbers.Inputs: A (float), B (float)Outputs: Result (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 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)

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

Get token/SOL balance (compact node).Inputs: Token Mint (string)Outputs: Balance (float)

Creating Connections

Connect nodes by dragging from output pins to input pins:
1

Click Output Pin

Click and hold on any output pin (right side of node).
2

Drag to Input

Drag the connection line to a compatible input pin (left side of target node).
3

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:
1

Open Palette

Click ”➕ Add Node” button in top-left corner.
2

Search or Browse

  • Type in search box to filter
  • Click category tabs (Events, Actions, Logic, Math, Web3)
3

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

1

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
}
2

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';
3

Action Pairing

Each edge creates a compiled action pairing an event with a response.
4

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

  • Group related nodes together
  • Use vertical space for parallel branches
  • Keep execution flow left-to-right
  • Add comments with Print String nodes
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

Build docs developers (and LLMs) love