Skip to content

Cocos Creator Blueprint Editor

This document explains how to install and use the blueprint visual scripting editor extension in Cocos Creator projects.

Download the cocos-node-editor.zip extension package from the release page.

  1. Open Cocos Creator
  2. Go to Extensions → Extension Manager
  3. Click the Import Extension button
  4. Select the downloaded cocos-node-editor.zip file
  5. Enable the extension after importing

Open the blueprint editor panel via menu Panel → Node Editor.

When opening the panel for the first time, the plugin will check if @esengine/blueprint is installed in your project. If not installed, it will display “Missing required dependencies” prompt. Click the “Install Dependencies” button to install automatically.

ButtonShortcutFunction
New-Create empty blueprint
Load-Load blueprint from file
SaveCtrl+SSave blueprint to file
UndoCtrl+ZUndo last operation
RedoCtrl+Shift+ZRedo operation
CutCtrl+XCut selected nodes
CopyCtrl+CCopy selected nodes
PasteCtrl+VPaste nodes
DeleteDeleteDelete selected items
Rescan-Rescan project for blueprint nodes
  • Right-click on canvas: Open node addition menu
  • Drag nodes: Move node position
  • Click node: Select node
  • Ctrl+Click: Multi-select nodes
  • Drag pin to pin: Create connection
  • Scroll wheel: Zoom canvas
  • Middle-click drag: Pan canvas

Right-clicking on canvas shows the node menu:

  • Search box at top for quick node search
  • Nodes grouped by category
  • Press Enter to quickly add first search result
  • Press Esc to close menu

Blueprints are saved as .blueprint.json files, fully compatible with runtime:

{
"version": 1,
"type": "blueprint",
"metadata": {
"name": "My Blueprint",
"createdAt": 1704307200000,
"modifiedAt": 1704307200000
},
"variables": [],
"nodes": [
{
"id": "node-1",
"type": "PrintString",
"position": { "x": 100, "y": 200 },
"data": {}
}
],
"connections": [
{
"id": "conn-1",
"fromNodeId": "node-1",
"fromPin": "exec",
"toNodeId": "node-2",
"toPin": "exec"
}
]
}

The @esengine/blueprint package provides complete ECS integration, including BlueprintComponent and BlueprintSystem ready to use.

import { BlueprintSystem } from '@esengine/blueprint';
// Add blueprint system during scene initialization
scene.addSystem(new BlueprintSystem());
import { resources, JsonAsset } from 'cc';
import { BlueprintComponent, validateBlueprintAsset, BlueprintAsset } from '@esengine/blueprint';
// Load blueprint asset
async function loadBlueprint(path: string): Promise<BlueprintAsset | null> {
return new Promise((resolve) => {
resources.load(path, JsonAsset, (err, asset) => {
if (err || !asset) {
console.error('Failed to load blueprint:', err);
resolve(null);
return;
}
const data = asset.json;
if (validateBlueprintAsset(data)) {
resolve(data as BlueprintAsset);
} else {
console.error('Invalid blueprint format');
resolve(null);
}
});
});
}
// Create entity with blueprint
async function createBlueprintEntity(scene: IScene, blueprintPath: string): Promise<Entity> {
const entity = scene.createEntity('BlueprintEntity');
const bpComponent = entity.addComponent(BlueprintComponent);
bpComponent.blueprintPath = blueprintPath;
bpComponent.blueprintAsset = await loadBlueprint(blueprintPath);
return entity;
}
PropertyTypeDescription
blueprintAssetBlueprintAsset | nullBlueprint asset data
blueprintPathstringBlueprint asset path (for serialization)
autoStartbooleanAuto-start execution (default true)
debugbooleanEnable debug mode
MethodDescription
start()Manually start blueprint execution
stop()Stop blueprint execution
cleanup()Cleanup blueprint resources

Use decorators to automatically generate blueprint nodes from components:

import { Component, ECSComponent } from '@esengine/ecs-framework';
import { BlueprintExpose, BlueprintProperty, BlueprintMethod } from '@esengine/blueprint';
@ECSComponent('Health')
@BlueprintExpose({ displayName: 'Health Component' })
export class HealthComponent extends Component {
@BlueprintProperty({ displayName: 'Current Health', category: 'number' })
current: number = 100;
@BlueprintProperty({ displayName: 'Max Health', category: 'number' })
max: number = 100;
@BlueprintMethod({ displayName: 'Heal', isExec: true })
heal(amount: number): void {
this.current = Math.min(this.current + amount, this.max);
}
@BlueprintMethod({ displayName: 'Take Damage', isExec: true })
takeDamage(amount: number): void {
this.current = Math.max(this.current - amount, 0);
}
@BlueprintMethod({ displayName: 'Is Dead' })
isDead(): boolean {
return this.current <= 0;
}
}
import { registerAllComponentNodes } from '@esengine/blueprint';
// Register all decorated components at application startup
registerAllComponentNodes();

For fully custom node logic:

import {
BlueprintNodeTemplate,
INodeExecutor,
RegisterNode,
ExecutionContext,
ExecutionResult
} from '@esengine/blueprint';
const MyNodeTemplate: BlueprintNodeTemplate = {
type: 'MyCustomNode',
title: 'My Custom Node',
category: 'custom',
description: 'Custom node example',
inputs: [
{ name: 'exec', type: 'exec', direction: 'input', isExec: true },
{ name: 'value', type: 'number', direction: 'input', defaultValue: 0 }
],
outputs: [
{ name: 'exec', type: 'exec', direction: 'output', isExec: true },
{ name: 'result', type: 'number', direction: 'output' }
]
};
@RegisterNode(MyNodeTemplate)
class MyNodeExecutor implements INodeExecutor {
execute(node: BlueprintNode, context: ExecutionContext): ExecutionResult {
const value = context.getInput<number>(node.id, 'value');
return {
outputs: { result: value * 2 },
nextExec: 'exec'
};
}
}
CategoryDescriptionColor
eventEvent nodesRed
flowFlow controlGray
entityEntity operationsBlue
componentComponent accessCyan
mathMath operationsGreen
logicLogic operationsRed
variableVariable accessPurple
timeTime utilitiesCyan
debugDebug utilitiesGray
customCustom nodesBlue-gray
  1. File Organization

    • Place blueprint files in assets/blueprints/ directory
    • Use meaningful file names like player-controller.blueprint.json
  2. Component Design

    • Use @BlueprintExpose to mark components that should be exposed to blueprints
    • Provide clear displayName for properties and methods
    • Mark execution methods with isExec: true
  3. Performance Considerations

    • Avoid heavy computation in Tick events
    • Use variables to cache intermediate results
    • Pure function nodes automatically cache outputs
  4. Debugging Tips

    • Use Print nodes to output intermediate values
    • Enable vm.debug = true to view execution logs

A: Click the Rescan button to scan for blueprint node classes in your project. Make sure you have called registerAllComponentNodes().

A: Check:

  1. Entity has BlueprintComponent added
  2. BlueprintExecutionSystem is registered to scene
  3. blueprintAsset is correctly loaded
  4. autoStart is true

A: Trigger through VM:

const bp = entity.getComponent(BlueprintComponent);
bp.vm?.triggerCustomEvent('OnPickup', { item: itemEntity });