A community-driven registry for Claude, Cursor, Windsurf, Cline & more. Not affiliated with Anthropic.
Are you the author? Sign in to claim
Unreal Engine Vibe Coding tool
VibeUE brings AI directly into Unreal Engine with an In-Editor Chat Client and Model Context Protocol (MCP) integration. Plan, inspect, create, and modify Blueprints, assets, materials, animation, landscapes, audio, UI, AI behavior, project settings, and more through natural language.
🔑 A free VibeUE API key is required for the MCP server and AI Chat to work. Get yours at vibeue.com/login — then paste it into the VibeUE settings gear icon inside Unreal Editor. See the AI Clients setup guide for IDE configuration.
VibeUE uses a Python-first architecture that gives AI assistants access to:
Lightweight MCP tools for AI interaction with Unreal:
| Tool | Purpose |
|---|---|
discover_python_module | Inspect module contents (classes, functions, constants) |
discover_python_class | Get class methods, properties, and inheritance |
discover_python_function | Get function signatures and docstrings |
execute_python_code | Run Python code in Unreal Editor context |
list_python_subsystems | List available UE editor subsystems |
vibeue-skills-manager | Load domain-specific knowledge on demand |
manage_asset | Search, open, save, move, duplicate, delete, and import (image files from disk) assets safely |
read_logs | Read and filter Unreal Engine log files with regex support |
terrain_data | Generate real-world heightmaps, map images, and water feature data from geographic coordinates |
deep_research | Web search, page fetching, and GPS geocoding — no API key required |
manage_editor_chat (optional) | Drive the in-editor AI chat for automated end-to-end testing. Hidden unless Chat Editor Testing mode is enabled — see In-Editor AI Chat → Chat Editor Testing. |
Note: The read_logs MCP tool provides access to Unreal Engine's log files for debugging, error analysis, and workflow understanding.
Note: The manage_asset MCP tool is the preferred path for asset search, save, move, duplicate, and delete workflows. It avoids ad hoc Python asset handling and preserves references when renaming or moving content.
Note: The terrain_data and deep_research tools work together for real-world terrain workflows: geocode a place name → generate a heightmap → import into a landscape → fetch water features.
discover_python_module
discover_python_module(
module_name: str, # e.g., "unreal" (lowercase for UE module)
name_filter: str = "", # Filter by name substring (case-insensitive)
include_classes: bool = True, # Include classes in results
include_functions: bool = True, # Include functions in results
max_items: int = 100, # Maximum items to return (0 = unlimited)
case_sensitive: bool = False # Whether filtering is case-sensitive
)
Example: discover_python_module("unreal", name_filter="Blueprint")
discover_python_class
discover_python_class(
class_name: str, # Fully qualified class name (e.g., "unreal.BlueprintService")
method_filter: str = "", # Filter methods by name substring
include_inherited: bool = False, # Include inherited methods
include_private: bool = False, # Include private methods starting with _
max_methods: int = 0 # Maximum methods to return (0 = unlimited)
)
Example: discover_python_class("unreal.BlueprintService", method_filter="variable")
discover_python_function
discover_python_function(
function_name: str # Fully qualified function name (e.g., "unreal.load_asset")
)
list_python_subsystems
list_python_subsystems() # No parameters - returns all UE editor subsystems
Usage: Access via unreal.get_editor_subsystem(unreal.SubsystemName)
execute_python_code
execute_python_code(
code: str # Python code to execute (must start with "import unreal")
)
Important: Use import unreal (lowercase). For subsystems: unreal.get_editor_subsystem(unreal.LevelEditorSubsystem)
Returns: stdout, stderr, and execution status
vibeue-skills-manager
# List all available skills
vibeue-skills-manager(action="list")
# Suggest skills based on query
vibeue-skills-manager(action="suggest", query="create widget button")
# Load single skill
vibeue-skills-manager(action="load", skill_name="blueprints")
# Load multiple skills together (more efficient - deduplicated discovery)
vibeue-skills-manager(action="load", skill_names=["blueprints", "enhanced-input"])
Skill names: animation-blueprint, animation-editing, animation-montage, animsequence, asset-management, blueprint-graphs, blueprints, data-assets, data-tables, engine-settings, enhanced-input, enum-struct, foliage, gameplay-tags, landscape, landscape-auto-material, landscape-materials, level-actors, map-blockout, materials, metasounds, niagara-emitters, niagara-systems, pcg, pie-testing, project-settings, screenshots, skeleton, sound-cues, state-trees, terrain-data, umg-widgets, uv-mapping, vibeue, viewport
Sub-docs (lazy-loaded deep reference material) — Several skills are split into a concise SKILL.md index plus sibling sub-docs. Load a sub-doc with skill_name="<skill>/<section>" (e.g. state-trees/api-reference, blueprint-graphs/build-graph, landscape/workflows-editing, map-blockout/workflows). The index response lists every available sub-doc under available_sections. This keeps each load small while keeping deep reference material one call away.
manage_asset
# Search before acting
manage_asset(action="search", search_term="BP_Player", asset_type="Blueprint")
# Open or save a specific asset
manage_asset(action="open", asset_path="/Game/Blueprints/BP_Player")
manage_asset(action="save", asset_path="/Game/Blueprints/BP_Player")
# Save everything dirty before a build or launch
manage_asset(action="save_all")
# Move or rename while preserving references
manage_asset(action="move", source_path="/Game/StateTree/STT_Rotate", destination_path="/Game/StateTree/Tasks/STT_Rotate")
# Import an image file from disk into the Content Browser (png/jpg/tga/exr/psd/...)
# Use this instead of Python import_asset_tasks, which crashes the editor from a tool call.
manage_asset(action="import", source_file_path="C:/Images/rocks.jpg", destination_path="/Game/UI/Textures", asset_name="T_Rocks")
Important: Use move, not duplicate + delete, when the intent is a rename or relocation. Duplicate creates a second asset identity.
read_logs
# List all logs
read_logs(action="list")
# Filter by category: System, Blueprint, Niagara, VibeUE
read_logs(action="list", category="Niagara")
# Get file info
read_logs(action="info", file="main")
# Read paginated content
read_logs(action="read", file="main", offset=0, limit=2000)
# Get last N lines
read_logs(action="tail", file="main", lines=50)
# Get first N lines
read_logs(action="head", file="main", lines=50)
# Regex filter with context
read_logs(
action="filter",
file="main",
pattern="ERROR|EXCEPTION",
context_lines=5,
max_matches=100,
case_sensitive=False
)
# Find errors
read_logs(action="errors", file="main", max_matches=20)
# Find warnings
read_logs(action="warnings", file="main", max_matches=20)
# Get new content since last read
read_logs(action="since", file="main", last_line=2500)
# Get help documentation
read_logs(action="help")
File Aliases:
main, system → Project log (FPS57.log)chat, vibeue → Chat history logllm → Raw LLM API logterrain_data
# Preview elevation stats and get suggested settings
terrain_data(action="preview_elevation", lng=-122.4194, lat=37.7749)
# Generate a heightmap matching your landscape resolution
terrain_data(
action="generate_heightmap",
lng=-122.4194, lat=37.7749,
base_level=0,
height_scale=100,
resolution=1009, # MUST match landscape resolution
format="png"
)
# Get a satellite or map reference image
terrain_data(
action="get_map_image",
lng=-122.4194, lat=37.7749,
style="satellite-v9" # satellite-v9, outdoors-v11, streets-v11, light-v10, dark-v10
)
# List available map image styles
terrain_data(action="list_styles")
# Fetch water features (rivers, lakes, ponds) for the same area
terrain_data(
action="get_water_features",
lng=-122.4194, lat=37.7749,
map_size=17.28
)
Parameters (generate_heightmap):
| Parameter | Type | Default | Description |
|---|---|---|---|
action | string | (required) | generate_heightmap, preview_elevation, get_map_image, list_styles, get_water_features |
lng | number | — | Longitude of center point |
lat | number | — | Latitude of center point |
format | string | png | Output: png, raw, zip |
resolution | number | 1081 | Output NxN pixels — MUST match landscape resolution |
map_size | number | 17.28 | Map size in km |
base_level | number | 0 | Base elevation offset in meters |
height_scale | number | 100 | Height scale % (1-250) |
water_depth | number | 40 | Water depth in C:S units |
blur_passes | number | 10 | Plains smoothing passes |
sharpen | boolean | true | Apply sharpening |
save_path | string | Saved/Terrain/ | Custom output path |
Workflow: preview_elevation → use suggested base_level and height_scale → generate_heightmap with resolution matching your landscape → import_heightmap via LandscapeService.
Water workflow: After importing a heightmap, call get_water_features with the same lng/lat/map_size. This saves a JSON file to Saved/Terrain/ with rivers (ue5_points) and water bodies (ue5_rings) in origin-centered UE5 coordinates. Use the saved JSON to create landscape splines for rivers and mesh planes for lakes.
deep_research
# Web search (DuckDuckGo)
deep_research(action="search", query="Unreal Engine landscape best practices")
# Fetch URL as clean markdown
deep_research(action="fetch_page", url="https://dev.epicgames.com/documentation/...")
# Place name → GPS coordinates
deep_research(action="geocode", query="Mount Fuji")
# GPS coordinates → place name
deep_research(action="reverse_geocode", lat=35.3606, lng=138.7274)
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | search, fetch_page, geocode, reverse_geocode |
query | string | For search/geocode | Search topic or place name |
url | string | For fetch_page | Full URL to fetch as markdown |
lat | number | For reverse_geocode | Latitude |
lng | number | For reverse_geocode | Longitude |
Typical workflows:
search → fetch_page on best URL → synthesizegeocode "Mount Fuji" → pass lat/lng to terrain_dataHigh-level services exposed to Python for common game development tasks:
| Service | Methods | Domain |
|---|---|---|
StateTreeService | 94 | StateTree asset creation, state hierarchy, state type/link configuration, editor selection, tasks, evaluators, conditions, transitions, delegate bindings, parameters, component overrides, property bindings, utility AI considerations, compile/save |
BlueprintService | 119 | Blueprint lifecycle, variables, functions, components, interfaces (add/remove), nodes, event dispatchers (multicast delegates) + broadcast nodes + bind-on-variable, custom event input pin CRUD, timelines (float/vector/color/event tracks, key CRUD), comment boxes, batch graph builder, subset auto-layout |
AnimSequenceService | 89 | Animation sequence creation, keyframes, bone tracks, curves, notifies, preview |
LandscapeService | 68 | Landscape creation, sculpting, heightmaps, weight layers, holes, splines |
MapBlockoutService | 19 | Procedural FPS map blockout — turn a VibeUE landscape (heightmap + paint layers) into a gated, AAA-style open-world plan (roads, POIs, fields, forests/treelines, railway/bridges), render Stage 1–5 + final heatmap/combined deliverables, then materialize as splines / paint layers / actors / foliage |
AnimMontageService | 62 | Animation montages: sections, slots, segments, branching points, blend settings |
SkeletonService | 53 | Skeleton & skeletal mesh manipulation, bones, sockets, retargeting, curves, blend profiles |
MaterialNodeService | 41 | Material graph expressions and connections, material diagnostics (compile errors + sampler info) |
WidgetService | 41 | UMG widget blueprints, components, snapshots, styling, animation, preview/PIE validation, and MVVM ViewModel bindings |
AnimGraphService | 48 | Animation Blueprint state machines, states, transitions, transition rules, declarative builder, validation, anim nodes |
SoundCueService | 38 | Sound cue graph editing, sound node creation, wiring, and audio behavior authoring |
NiagaraService | 37 | Niagara system lifecycle, emitters, parameters, settings discovery |
ActorService | 33 | Level actor management, viewport camera control, transform lock/constraints |
MaterialService | 30 | Materials and material instances |
EngineSettingsService | 23 | Engine settings, rendering, physics, audio, cvars, scalability |
InputService | 23 | Enhanced Input actions, contexts, modifiers, triggers |
NiagaraEmitterService | 23 | Niagara emitter modules, renderers, properties |
NiagaraScratchPadService | 19 | Niagara scratch-pad module authoring: create modules, add Map Get/Set/Op/Custom HLSL nodes, typed pins, wire pins, declare module inputs/outputs |
LandscapeMaterialService | 22 | Landscape material layers, blend nodes, auto-material creation, layer info objects, grass output |
UVMappingService | 22 | Per-LOD UV channel inspection, transforms, lightmap generation, per-region edits (by normal / polygon group / UV island), auto-unwrap (planar/box/cylindrical), packing, layout export |
EnumStructService | 20 | User-defined enums and structs (create, edit, delete) |
AssetDiscoveryService | 21 | Asset search, import (image files from disk) / export, references, move/rename workflows |
ViewportService | 19 | Viewport camera type (perspective/ortho), view mode, FOV, clip planes, exposure, game view, cinematic control, camera speed, viewport layout (single/quad) |
MetaSoundService | 17 | MetaSound graph authoring, nodes, interfaces, inputs/outputs, and wiring |
ProjectSettingsService | 16 | Project settings, editor preferences, UI configuration |
EditorTransactionService | 16 | Undo/redo, transaction grouping, history inspection, buffer reset |
FoliageService | 15 | Foliage type management, scatter placement, layer-aware painting, instance queries |
DataTableService | 15 | DataTable rows and structure |
DataAssetService | 11 | UDataAsset instances and properties |
GameplayTagService | 8 | Gameplay tag CRUD: add, remove, rename, list, filter, hierarchy inspection |
ScreenshotService | 6 | Editor window, viewport, and per-asset-editor screenshot capture for AI vision |
RuntimeVirtualTextureService | 4 | Runtime Virtual Texture assets, RVT volume actors, and landscape RVT assignment |
Direct access to all unreal.* modules:
unreal.EditorAssetLibrary - Asset operationsunreal.EditorActorSubsystem - Level actor manipulation (via unreal.get_editor_subsystem())unreal.EditorLevelLibraryEditorActorSubsystem insteadunreal.EditorUtilityLibrary - Editor utilitiesunreal.SystemLibrary - System functionscd /path/to/your/unreal/project/Plugins
git clone https://github.com/kevinpbuckley/VibeUE.git
Double-click to build:
Plugins/VibeUE/BuildPlugin.bat
Or specify your Unreal Engine path explicitly (skips auto-detection):
Plugins/VibeUE/BuildPlugin.bat "C:\Program Files\Epic Games\UE_5.7"
If the provided path is invalid, the script falls back to automatic detection.
⚠️ Required for MCP tools: The VibeUE API key is validated at startup. If no valid key is configured, all MCP tools will return an error. Get your free key at vibeue.com/login.
VibeUE automatically enables these required plugins during installation:
| Plugin | Purpose |
|---|---|
| PythonScriptPlugin | Python runtime and Unreal Engine Python API |
| EditorScriptingUtilities | Blueprint and asset manipulation APIs |
| EnhancedInput | Input system discovery and configuration |
| AudioCapture | Speech-to-text input for in-editor chat |
| Niagara | Niagara VFX system and emitter manipulation |
| MeshModelingToolset | Skeleton modifier for bone manipulation |
The built-in chat interface runs directly in Unreal Editor:
Window > VibeUE > AI Chat| Setting | Default | Description |
|---|---|---|
| LLM Provider | VibeUE | Select VibeUE or OpenRouter |
| Temperature | 0.2 | Creativity (0.0-1.0) |
| Max Tool Iterations | 100 | Max tool calls per turn |
| Chat Editor Testing | Off | Exposes the optional manage_editor_chat MCP tool (see below) |
A testing mode that lets an external agent drive the in-editor AI chat end-to-end — useful for
automated regression runs of skills/services against a live editor. When enabled, the MCP server exposes
one extra tool, manage_editor_chat; it is hidden by default so normal users and the in-editor
chat AI never see it.
Enable it any of these ways:
[VibeUE] ChatEditorTesting=True in EditorPerProjectUserSettings.ini-VibeUEChatTestingmanage_editor_chat actions: open_chat, send_message, check_chat_status, get_messages,
get_last_response, stop_chat, reset_chat (with optional archive_log), approve_tool /
reject_tool, set_yolo_mode, set_model, archive_chat_log, get_chat_log_path, help.
send_messageis asynchronous: pollcheck_chat_statusuntilis_idle=true, then callget_last_response. Enableset_yolo_modefor unattended runs so Python execution auto-approves.
The in-editor chat has a memory that persists between editor sessions, so the assistant can recall things you've asked it to remember in earlier conversations (project conventions, decisions, recurring preferences, where things live, etc.).
<YourProject>/Saved/VibeUE/Memory. It's per-project and local to your machine — nothing is committed to source control and nothing is sent to external services beyond the normal chat request. You can browse, back up, or clear these files yourself at any time.view, create, str_replace, insert, delete, rename — scoped to the memory folder (paths outside it are rejected).The assistant's memory behavior is defined in
Content/instructions/vibeue.instructions.md— edit that file to tune how aggressively it recalls or what it's allowed to store.
When using VibeUE's MCP server with external AI agents (Claude Code, GitHub Copilot, Cursor, Antigravity, etc.), you must include the VibeUE instructions in your AI system prompt or context.
Ready-made templates: See
Content/samples/README.mdfor copy-paste setup instructions for each supported AI tool.
The Plugins/VibeUE/Content/instructions/vibeue.instructions.md file contains:
Without these instructions, AI agents will make incorrect assumptions about the API and encounter failures.
Create CLAUDE.md at your project root:
# My Unreal Project
@Plugins/VibeUE/Content/samples/AGENTS.md.sample
The @ directive inlines the file automatically — no copying needed.
Copy Plugins/VibeUE/Content/samples/AGENTS.md.sample to your project root as AGENTS.md. Read by OpenAI Codex, Cursor, and other agents that follow the AGENTS.md convention.
Copy Plugins/VibeUE/Content/samples/AGENTS.md.sample to:
.github/copilot-instructions.md
Copy Plugins/VibeUE/Content/samples/AGENTS.md.sample to:
.cursor/rules/vibeue.mdc
Copy Plugins/VibeUE/Content/samples/AGENTS.md.sample to:
.agent/rules/vibeue.md
The AI must know:
discover_python_class() before calling service methods/Game/Path/Asset, not Asset)vibeue-skills-manager for domain-specific knowledgeVibeUE uses a Skills System to dramatically reduce AI context overhead while providing domain-specific guidance.
Instead of loading all documentation at once, skills are lazy-loaded on demand:
vibeue-skills-manager tooldiscover_python_classEach skill includes:
Domain Skills (dynamically discovered from Content/Skills/*/SKILL.md):
Skills are automatically discovered at runtime from the Content/Skills/ directory. Each skill folder contains a SKILL.md with YAML frontmatter defining its metadata. The system prompt's {SKILLS} token is replaced with a dynamically generated table of all available skills.
Current skills include: animation-blueprint, animation-editing, animation-montage, animsequence, asset-management, blueprint-graphs, blueprints, data-assets, data-tables, engine-settings, enhanced-input, enum-struct, foliage, gameplay-tags, landscape, landscape-auto-material, landscape-materials, level-actors, map-blockout, materials, metasounds, niagara-emitters, niagara-systems, pcg, pie-testing, project-settings, screenshots, skeleton, sound-cues, state-trees, terrain-data, umg-widgets, uv-mapping, vibeue, viewport
Skills with sub-docs — animsequence, blueprint-graphs, landscape, landscape-auto-material, map-blockout, and state-trees are split into a concise SKILL.md index plus sibling reference sub-docs. The index lists every available sub-doc under available_sections and you load one with skill_name="<skill>/<section>". Examples: state-trees/api-reference, state-trees/blueprint-tasks, state-trees/event-payloads, blueprint-graphs/build-graph, blueprint-graphs/array-operations, landscape/workflows-editing, map-blockout/workflows, map-blockout/stage-rules.
In-Editor Chat - Skills auto-load based on keywords
External AI - Manually load with vibeue-skills-manager tool:
# List all available skills
vibeue-skills-manager(action="list")
# Load a specific skill
vibeue-skills-manager(action="load", skill_name="blueprints")
# Load multiple skills together (deduplicated discovery)
vibeue-skills-manager(action="load", skill_names=["blueprints", "enhanced-input"])
Skill response includes:
vibeue_classes - Services to discover (e.g., BlueprintService)unreal_classes - Native UE classes (e.g., EditorAssetLibrary)content - Markdown with workflows and critical rulesCOMMON_MISTAKES - Quick reference for frequent errorsavailable_sections - Loadable sub-docs (deeper reference material). Each entry has a name and short description; load one with skill_name="<skill>/<section>".loaded_section - Present only when a sub-doc was loaded; identifies which file the response came from.The recommended pattern:
import unreal
# 1. Load relevant skill for domain knowledge
vibeue-skills-manager(action="load", skill_name="blueprints")
# ↓ Skill response tells you about BlueprintService methods and critical rules
# 2. Discover exact method signatures BEFORE calling
unreal.BlueprintService # Already know this from skill
discover_python_class("unreal.BlueprintService", method_filter="variable")
# ↓ Discovery returns: add_variable, remove_variable, list_variables, ...
# 3. Use discovered signatures with parameters from skill
path = unreal.BlueprintService.create_blueprint("BP_Player", "Actor", "/Game/Blueprints")
unreal.BlueprintService.add_variable(path, "Health", "Float", "100.0")
unreal.BlueprintService.compile_blueprint(path) # Critical rule from skill!
Before Skills: 13,000 tokens of all docs loaded every conversation
After Skills: 2,500 base + domain skills on demand
All services are available via unreal.<ServiceName>.<method>().
# ALWAYS discover service methods first
# MCP: discover_python_class("unreal.BlueprintService")
# Then call methods with correct parameters
unreal.BlueprintService.create_blueprint("BP_MyActor", "Actor", "/Game/Blueprints")
Lifecycle:
create_blueprint(name, parent_class, path) - Create new blueprintcompile_blueprint(path) - Compile blueprintreparent_blueprint(path, new_parent) - Change parent classget_blueprint_info(path) - Detailed info (variables, functions, components, parent)Variables:
add_variable(path, name, type, default, ...) - Add variableremove_variable(path, name) - Remove variablelist_variables(path) - List all variablesget_variable_info(path, name) - Get variable detailsmodify_variable(path, name, ...) - Modify properties (rename, category, flags, replication)set_variable_default_value(path, name, value) - Update only the defaultsearch_variable_types(filter, category) - Find available typesFunctions:
create_function(path, name, is_pure) - Create functiondelete_function(path, name) - Delete functionadd_function_input/output(...) - Add parametersadd_function_local_variable(...) - Add local variablesget_function_info(path, name) - Get function detailsoverride_function(path, function_name) - Override an inherited virtual/event functionComponents:
add_component(path, type, name, parent) - Add componentremove_component(path, name) - Remove componentreparent_component(path, name, new_parent) - Reparent in the SCS hierarchyget/set_component_property(...) - Property accessget_component_hierarchy(path) - Get hierarchyInterfaces:
add_interface(path, interface) - Implement a Blueprint Interface (idempotent; recompiles inline)remove_interface(path, interface) - Remove a Blueprint InterfaceNodes & Graph Editing:
add_*_node(...) - Add nodes (branch, variable, math, cast, event, custom event, function call, etc.)add_validated_get_node(...), add_member_get_node(...) - Specialized variable getter nodesadd_function_call_on_variable(...) - One-shot getter + call on a variableconnect_nodes(...), disconnect_pin(...) - Wire / unwire pinsset_node_pin_value(...), split_pin(...), recombine_pin(...) - Per-pin editsget_nodes_in_graph(path, graph), get_connections(...), get_node_pins(...), get_node_details(...) - Inspect graphsget_selected_nodes(path) - Read the user's live editor selectiondiscover_nodes(path, search) / create_node_by_key(...) - Action-database-driven node lookup + spawnbuild_graph(...) - Batch graph builder (create many nodes + connections in one shot)auto_layout_graph(...), auto_layout_selected_nodes(...) - Apply UE auto-layoutadd_comment_node(...), add_comment_around_nodes(...) - Comment-box authoring (programmatic equivalent of the C hotkey)delete_node(...), node_exists(...), refresh_node(...) - Node lifecycleCustom Events (full input-pin CRUD):
add_custom_event_node(path, graph, name, x, y) - Create a Custom Eventadd_custom_event_input(path, graph, node_id, param_name, type, ...) - Add a user-defined input pinget_custom_event_inputs(path, graph, node_id) - Inspect existing inputsmodify_custom_event_input(path, graph, node_id, param_name, new_name, new_type, ...) - Rename/retype (preserves connections where compatible)remove_custom_event_input(path, graph, node_id, param_name) - Remove a pinEvent Dispatchers (Blueprint multicast delegates):
add_event_dispatcher(path, name) - Add a dispatcher (member variable + signature graph; skeleton recompiles inline)remove_event_dispatcher(path, name) - Remove the dispatcher and its signature graphadd_event_dispatcher_parameter(path, name, param_name, param_type, ...) - Add an input on the signatureadd_call_delegate_node(path, graph, name, x, y) - Spawn the UK2Node_CallDelegate (broadcast) nodeadd_delegate_bind_node(path, graph, target_class, delegate_name, x, y) - Spawn a Bind Event node to subscribe. target_class accepts "Self", native class names, Blueprint asset paths, or short BP names with/without _Cadd_delegate_bind_on_variable(path, graph, variable_name, delegate_name, x, y) - One-shot: derives owner class from a variable's type, creates Bind Event + Get, auto-wires Target (mirrors add_function_call_on_variable)add_create_delegate_node(...), add_create_event_node(...) - Wrap a function as a delegate referenceTimelines (full track + key CRUD):
add_timeline(path, graph, name, length, use_last_key, auto_play, loop, x, y) - Create a Timeline component + nodemodify_timeline(...), remove_timeline(...), get_timelines(path) - Lifecycle / inspectionadd_timeline_float_track, add_timeline_vector_track, add_timeline_color_track, add_timeline_event_track - Add tracks (each adds the matching output pin on the Timeline node)rename_timeline_track(...), remove_timeline_track(...), clear_timeline_track_keys(...) - Track managementadd_timeline_float_key, add_timeline_vector_key, add_timeline_color_key, add_timeline_event_key - Keyframe authoring with selectable interp modes (Auto/Linear/Constant/CubicUser)remove_timeline_key(...) - Remove a key by handle/indexIntrospection:
list_components, list_variables, list_functions, list_function_local_variables, list_overridable_functionsget_function_parameters(...), get_graph_definition(...), get_available_components(...)compare_components(...), diff_blueprints(...)AnimGraphService provides comprehensive Animation Blueprint manipulation for state machines, states, transitions, transition rules, and animation nodes — including a declarative one-call builder and a validation pass so AI-authored machines actually run:
High-Level Authoring (recommended):
build_state_machine(path, machine, spec_json, x, y) - Build/extend an entire state machine (states, animations, transitions, rules, entry) from one JSON spec, atomically and idempotently; compiles and returns a JSON reportset_state_animation(path, machine, state, anim_path, loop, play_rate) - One call: create/assign the state's sequence player AND wire it to Output Posevalidate_state_machine(path, machine) - Report inert transitions, missing entry state, states with no animation, unreachable statesTransition Rules (a transition with NO rule never fires):
set_transition_rule_from_bool(path, machine, source, dest, bool_var, invert) - Drive a transition from a bool variableset_transition_rule_comparison(path, machine, source, dest, float_var, op, value) - Numeric comparison rule (greater/less/greater_equal/less_equal/equal/not_equal)set_transition_rule_automatic(path, machine, source, dest, trigger_time) - Auto-fire when the source state's animation is (almost) finished (one-shots)clear_transition_rule(path, machine, source, dest) - Non-destructively reset a transition's ruleState Machine Management:
add_state_machine(path, name, x, y) - Add state machine to AnimGraphlist_state_machines(path) - List all state machinesget_state_machine_info(path, name) - Get detailed state machine infoState Management:
add_state(path, machine, name, x, y) - Add state to state machineremove_state(path, machine, name, remove_transitions) - Remove stateset_entry_state(path, machine, state) - Set the entry/default state (non-destructive re-link)list_states_in_machine(path, machine) - List all states and transitionsget_state_info(path, machine, state) - Get detailed state infoopen_anim_state(path, machine, state) - Open state in editorTransition Management:
add_transition(path, machine, source, dest, blend_duration) - Add transition (remember to set a rule!)remove_transition(path, machine, source, dest) - Remove transitionset_transition_priority(path, machine, source, dest, priority) - Set priority order (lower wins)set_transition_blend(path, machine, source, dest, blend_duration, blend_mode) - Set crossfade duration / blend modeget_state_transitions(path, machine, state) - Get transitions for state (now includes rule_type/rule_summary/has_rule)open_transition(path, machine, source, dest) - Open transition rule in editorConduit Management:
add_conduit(path, machine, name, x, y) - Add conduit nodeAnimation Nodes:
add_sequence_player(path, graph, anim_path, x, y) - Add sequence playeradd_blend_space_player(path, graph, bs_path, x, y) - Add blend space playeradd_blend_by_bool(path, graph, x, y) - Add Blend By Bool nodeadd_blend_by_int(path, graph, num_poses, x, y) - Add Blend By Int nodeadd_layered_blend(path, graph, x, y) - Add Layered Blend Per Boneadd_slot_node(path, graph, slot_name, x, y) - Add slot nodeadd_save_cached_pose(path, graph, cache_name, x, y) - Add Save Cached Poseadd_use_cached_pose(path, graph, cache_name, x, y) - Add Use Cached Poseadd_two_bone_ik_node(path, graph, x, y) - Add Two Bone IKadd_modify_bone_node(path, graph, bone_name, x, y) - Add Modify BoneNode Connections:
connect_anim_nodes(path, graph, source_id, source_pin, target_id, target_pin) - Connect pose pinsconnect_to_output_pose(path, graph, source_id, source_pin) - Connect to Output Posedisconnect_anim_node(path, graph, node_id, pin_name) - Disconnect nodeAsset Management:
set_sequence_player_asset(path, graph, node_id, anim_path) - Set animation on playerset_blend_space_asset(path, graph, node_id, bs_path) - Set blend space on playerget_node_animation_asset(path, graph, node_id) - Get current animation assetInformation & Navigation:
is_anim_blueprint(path) - Check if asset is AnimBPget_skeleton(path) - Get skeleton used by AnimBPget_preview_mesh(path) - Get preview skeletal meshget_parent_class(path) - Get parent classget_output_pose_node_id(path, graph) - Get Output Pose node IDget_used_anim_sequences(path) - List all used animationslist_graphs(path) - List all graphs in AnimBPopen_anim_graph(path, graph) - Open graph in editorfocus_node(path, node_id) - Focus on specific nodeAnimMontageService provides comprehensive CRUD operations for Animation Montage assets including section management, slot tracks, animation segments, branching points, and blend settings:
Discovery:
list_montages(path, skeleton_filter) - List all montages in a pathget_montage_info(path) - Get comprehensive montage informationfind_montages_for_skeleton(skeleton_path) - Find all montages compatible with a skeletonfind_montages_using_animation(anim_path) - Find montages using a specific animationProperties:
get_montage_length(path) - Get total duration in secondsget_montage_skeleton(path) - Get skeleton asset pathset_blend_in(path, time, option) - Set blend in settings (Linear, Cubic, etc.)set_blend_out(path, time, option) - Set blend out settingsget_blend_settings(path) - Get all blend settingsset_blend_out_trigger_time(path, time) - Set when blend out beginsSection Management (C++ - required for TArray modification):
list_sections(path) - List all sections with timing infoget_section_info(path, name) - Get detailed section infoget_section_index_at_time(path, time) - Get section index at timeget_section_name_at_time(path, time) - Get section name at timeadd_section(path, name, start_time) - Add new sectionremove_section(path, name) - Remove sectionrename_section(path, old_name, new_name) - Rename sectionset_section_start_time(path, name, time) - Move sectionget_section_length(path, name) - Get section durationSection Linking (Branching):
get_next_section(path, section) - Get linked next sectionset_next_section(path, section, next) - Link section to nextset_section_loop(path, section, loop) - Set section to loopget_all_section_links(path) - Get complete flow chartclear_section_link(path, section) - Clear link (ends montage)Slot Tracks:
list_slot_tracks(path) - List all slot tracksget_slot_track_info(path, index) - Get track detailsadd_slot_track(path, slot_name) - Add new slot trackremove_slot_track(path, index) - Remove trackset_slot_name(path, index, name) - Change slot nameget_all_used_slot_names(path) - Get unique slot namesAnimation Segments (Multiple Animations per Montage):
list_anim_segments(path, track_index) - List segments in trackget_anim_segment_info(path, track, segment) - Get segment detailsadd_anim_segment(path, track, anim_path, start_time, play_rate) - Add animationremove_anim_segment(path, track, segment) - Remove segmentset_segment_start_time(path, track, segment, time) - Move segmentset_segment_play_rate(path, track, segment, rate) - Set playback speedset_segment_start_position(path, track, segment, pos) - Trim startset_segment_end_position(path, track, segment, pos) - Trim endset_segment_loop_count(path, track, segment, count) - Set loop countNotifies:
list_notifies(path) - List all notifiesadd_notify(path, class, time, name) - Add instant notifyadd_notify_state(path, class, start, duration, name) - Add state notifyremove_notify(path, index) - Remove notifyset_notify_trigger_time(path, index, time) - Move notifyset_notify_link_to_section(path, index, section) - Link to sectionBranching Points:
list_branching_points(path) - List all branching pointsadd_branching_point(path, name, time) - Add frame-accurate eventremove_branching_point(path, index) - Remove branching pointis_branching_point_at_time(path, time) - Check for branching pointRoot Motion:
get/set_enable_root_motion_translation(path, enable) - Control translationget/set_enable_root_motion_rotation(path, enable) - Control rotationget_root_motion_at_time(path, time) - Get root motion transformCreation:
create_montage_from_animation(anim, dest, name) - Create from animationcreate_empty_montage(skeleton, dest, name) - Create empty montageduplicate_montage(source, dest, name) - Duplicate montageEditor:
open_montage_editor(path) - Open in Animation Editorrefresh_montage_editor(path) - Refresh UI after modificationsjump_to_section(path, section) - Preview jump to sectionset_preview_time(path, time) - Set preview playheadplay_preview(path, start_section) - Play in previewLifecycle:
create_material(name, path) - Create materialcreate_instance(parent, name, path) - Create instancecompile_material(path) - Recompile shadersProperties:
get/set_property(path, name, value) - Property accesslist_properties(path) - List all propertieslist_parameters(path) - List parametersInstances:
set_instance_scalar/vector/texture_parameter(...) - Set overridesclear_instance_parameter_override(...) - Clear overridediscover_types(category, search) - Find expression typescreate_expression(path, class, x, y) - Create expressionconnect_expressions(...) - Connect nodesconnect_to_output(path, expr, output, property) - Connect to material outputcreate_parameter(...) - Create parameter expressionlist_widget_blueprints(path), widget_blueprint_exists(path), widget_exists(path, component) - Discover widget assets and validate targets before editingget_hierarchy(path), get_root_widget(path), list_components(path) - Inspect widget trees and hierarchy stateget_widget_snapshot(path), get_component_snapshot(path, component) - Capture hierarchy, slot layout, and property state in a single calladd_component(path, type, name, parent), remove_component(path, name), rename_widget(path, old_name, new_name), validate(path) - Manage widget composition safelyget_component_properties(path, component), list_properties(path, component), get/set_property(path, component, property, value), search_types(filter) - Query and edit widget properties and available typesget_available_events(path, component, type), bind_event(path, widget, event, function) - Discover and wire widget eventsadd_view_model(path, class, name, creation_type), remove_view_model(path, name), list_view_models(path) - Register MVVM ViewModelsadd_view_model_binding(path, vm, vm_prop, widget, widget_prop, mode), remove_view_model_binding(path, index), list_view_model_bindings(path) - Create and manage MVVM bindingsset_font/get_font(...), set_brush/get_brush(...) - Apply full font and brush styling APIs for UMG widgetslist_animations(path), create_animation(path, name), remove_animation(path, name), add_animation_track(path, anim, widget, property), add_keyframe(path, anim, widget, property, keyframe) - Author UMG animationscapture_preview(path), start_pie(), stop_pie(), is_pie_running(), spawn_widget_in_pie(path), get_live_property(handle, component, property), remove_widget_from_pie(handle) - Preview and runtime validation workflowscreate_action(name, path, value_type) - Create Input Actioncreate_mapping_context(name, path, priority) - Create contextadd_key_mapping(context, action, key) - Add bindingadd_modifier/trigger(...) - Add modifiers/triggersget_available_keys(filter) - List bindable keyssearch_assets(term, type) - Find assetssave_asset(path) / save_all_assets() - Saveimport_asset(file, dest_folder, name) - Import an image file from disk (crash-safe; returns asset path + error)import_texture(file, dest) - Import texture (full asset path; uses the same safe importer)export_texture(asset, file) - Export textureget_asset_dependencies/referencers(path) - Referencessearch_types(filter) - Find DataAsset subclassescreate_data_asset(class, path, name) - Create instanceget/set_property(path, name, value) - Property accessset_properties(path, json) - Bulk set propertiessearch_row_types(filter) - Find row struct typescreate_data_table(struct, path, name) - Create tableadd_row/add_rows(path, name, json) - Add rowsget_row/update_row/remove_row(...) - Row operationsget_row_struct(path) - Get column schemaActorService provides comprehensive level actor manipulation:
Camera Control:
set_viewport_camera(location, rotation) — Position the editor viewport camera directlyget_actor_view_camera(name, direction, padding) — Calculate and apply a camera view that frames an actor from a direction (Top, Bottom, Left, Right, Front, Back)calculate_actor_view(name, direction, padding) — Calculate view info without moving the cameraTransform Lock / Constraints:
set_actor_lock_location(name, locked) — Lock/unlock an actor's location in the editorget_actor_lock_location(name) — Query whether an actor's location is lockedset_absolute_transform(name, location, rotation, scale) — Set absolute (world-space) flags for location, rotation, scaleget_absolute_transform(name) — Query current absolute transform flagsset_preserve_scale_ratio(enabled) — Toggle the global "Preserve Scale Ratio" editor preference (padlock icon)get_preserve_scale_ratio() — Query whether the scale ratio padlock is enabledSkeletonService provides comprehensive skeleton and skeletal mesh manipulation:
Discovery:
search_skeletons(path, filter) - Find skeleton assetssearch_skeletal_meshes(path, filter) - Find skeletal mesh assetsget_skeleton_info(path) - Get skeleton metadataget_mesh_skeleton(path) - Get skeleton used by a meshget_meshes_using_skeleton(path) - Find all meshes using a skeletonBone Operations:
list_bones(path) - List all bones with hierarchyget_bone_info(path, name) - Get detailed bone infoget_bone_hierarchy(path, name, depth) - Get bone subtreeget_bone_children(path, name) - Get direct childrenget_bone_transform(path, name, space) - Get transform (local/global)find_bone_by_index(path, index) - Find bone by indexbone_exists(path, name) - Check if bone existsget_bone_path_to_root(path, name) - Get chain from bone to rootBone Modification (requires commit):
add_bone(path, name, parent, transform) - Add new boneremove_bone(path, name, remove_children) - Remove bonerename_bone(path, old_name, new_name) - Rename bonemirror_bone(path, name, axis, prefix) - Mirror bonereparent_bone(path, name, new_parent) - Change parentset_bone_transform(path, name, transform, space) - Set transformcopy_bone_chain(path, source, new_parent, prefix) - Duplicate chaincommit_bone_changes(path) - CRITICAL: Apply all changesSockets:
list_sockets(path) - List all socketsget_socket_info(path, name) - Get socket detailsadd_socket(path, name, bone, location, rotation, scale, to_skeleton) - Add socketremove_socket(path, name) - Remove socketsocket_exists(path, name) - Check if socket existsupdate_socket(path, name, ...) - Modify socket propertiescopy_socket(path, source, new_name, new_bone) - Duplicate socketRetargeting:
get_bone_retargeting_mode(path, name) - Get retarget modeset_bone_retargeting_mode(path, name, mode) - Set retarget modeget_all_retargeting_modes(path) - Get all bones' modesset_batch_retargeting_mode(path, bones, mode) - Set multiple bonesCurve Metadata:
list_curves(path) - List curve metadataadd_curve(path, name, morph, material) - Add curveremove_curve(path, name) - Remove curveget_curve_info(path, name) - Get curve detailsset_curve_flags(path, name, morph, material) - Set curve flagscurve_exists(path, name) - Check if curve existsBlend Profiles:
list_blend_profiles(path) - List profilesget_blend_profile(path, name) - Get profile datacreate_blend_profile(path, name) - Create profileset_blend_profile_scale(path, profile, bone, scale, children) - Set blend scaleProperties & Editor:
get_preview_mesh(path) - Get preview meshset_preview_mesh(path, mesh) - Set preview meshget_physics_asset(mesh) - Get associated physics assetopen_in_editor(path) - Open in Skeleton Tree editoropen_mesh_in_editor(path) - Open skeletal mesh editorrefresh_skeleton(path) - Refresh after changesLandscapeService provides comprehensive landscape terrain manipulation including sculpting, weight layer painting, heightmap import/export, visibility holes, and spline-based road/path creation:
Discovery:
list_landscapes() - Find all landscape actors in the current levelget_landscape_info(name) - Get landscape metadata (size, components, layers)landscape_exists(name) / layer_exists(name, layer) - Existence checksLifecycle:
create_landscape(name, ...) - Create a new landscape actordelete_landscape(name) - Remove a landscape actorHeightmap Operations:
import_heightmap(name, file) - Import heightmap from PNG/R16 fileexport_heightmap(name, file) - Export heightmap to fileget_height_at_location(name, x, y) - Sample height at world positionget_height_in_region(name, ...) - Get heights across a regionset_height_in_region(name, ...) - Set heights across a regionSculpting:
sculpt_at_location(name, x, y, radius, strength) - Raise/lower terrainflatten_at_location(name, x, y, radius, height) - Flatten to target heightsmooth_at_location(name, x, y, radius, strength) - Smooth terrainraise_lower_region(name, ...) - Raise or lower a rectangular regionapply_noise(name, ...) - Apply procedural noisePaint Layer Operations:
list_layers(name) - List all landscape layersadd_layer(name, layer, ...) - Add a paint layerremove_layer(name, layer) - Remove a paint layerget_layer_weights_at_location(name, x, y) - Sample layer weightspaint_layer_at_location(name, layer, x, y, radius, strength) - Paint a layerpaint_layer_in_region(name, layer, ...) - Batch paint a regionpaint_layer_in_world_rect(name, layer, ...) - Paint in world-space rectWeight Map Import/Export:
export_weight_map(name, layer, file) - Export layer weight mapimport_weight_map(name, layer, file) - Import layer weight mapget_weights_in_region(name, ...) - Read weights across a regionset_weights_in_region(name, ...) - Write weights across a regionVisibility Holes:
get_hole_at_location(name, x, y) - Check if hole exists at locationset_hole_at_location(name, x, y, hole) - Create/remove a holeset_hole_in_region(name, ...) - Set holes across a regionSplines:
create_spline_point(name, x, y, z) - Create a landscape spline pointconnect_spline_points(name, p1, p2) - Connect two spline pointscreate_spline_from_points(name, points) - Create a spline from a list of positionsget_spline_info(name) - Get all spline points and segmentsmodify_spline_point(name, index, ...) - Move or adjust a spline pointdelete_spline_point(name, index) - Remove a spline pointdelete_all_splines(name) - Clear all splines on the landscapeapply_splines_to_landscape(name) - Bake splines into the terrain shapeset_spline_segment_meshes(name, segment, mesh) - Assign mesh to spline segmentset_spline_point_mesh(name, index, mesh) - Assign mesh at spline pointProperties:
get_landscape_property(name, prop) / set_landscape_property(name, prop, val) - Property accessset_landscape_material(name, material) - Assign material to landscapeset_landscape_visibility(name, visible) / set_landscape_collision(name, enabled) - Visibility and collisionResize:
resize_landscape(name, ...) - Change landscape dimensionsLandscapeMaterialService handles the creation and configuration of landscape-specific materials including layer blend nodes, layer info objects, and grass output:
Material Creation:
create_landscape_material(name, path) - Create a landscape-compatible materialLayer Blend Nodes:
create_layer_blend_node(material, x, y) - Create a LandscapeLayerBlend nodecreate_layer_blend_node_with_layers(material, layers, x, y) - Create node with predefined layersadd_layer_to_blend_node(material, node_id, layer_name, blend_type) - Add layer to blend noderemove_layer_from_blend_node(material, node_id, layer_name) - Remove layer from blend nodeget_layer_blend_info(material, node_id) - Get blend node configurationconnect_to_layer_input(material, node_id, layer, texture) - Connect texture to layer inputLandscape-Specific Expressions:
create_layer_coords_node(material, x, y) - Create LandscapeLayerCoords UV nodecreate_layer_sample_node(material, layer, x, y) - Create LandscapeLayerSample nodecreate_layer_weight_node(material, layer, x, y) - Create LandscapeLayerWeight expressioncreate_grass_output(material, grass_types, x, y) - Create LandscapeGrassOutput nodeLayer Info Objects:
create_layer_info_object(name, path, layer_name) - Create a LandscapeLayerInfoObject assetget_layer_info_details(path) - Get layer info properties (phys material, hardness, etc.)Material Assignment:
assign_material_to_landscape(landscape, material) - Assign material to a landscape actorConvenience:
setup_layer_textures(material, layers) - One-call setup for multi-layer textured landscape materialExistence Checks:
landscape_material_exists(path) / layer_info_exists(path) - Existence checksMapBlockoutService turns a VibeUE-generated landscape (heightmap + paint layers) into a fully validated, AAA-style open-world FPS map blockout — roads, points of interest, fields, forests/treelines, railway, and bridges — then materializes that plan into real engine geometry. The quality benchmark is Arma / Squad.
The design pipeline is gated: every stage runs ordered pass/fail checks, and you may not advance until all checks pass. Phase 1 designs the plan on the CPU (masks + polylines, no engine geometry); Phase 2 materializes it into the level. Load the map-blockout skill for the per-stage rules, config reference, and return-type shapes.
Input (Stage 0):
export_landcover_grid(landscape_label, grid_n=120) - Read every paint layer + the heightmap off the source landscape and return a normalized landcover grid (replaces the host-Python export_terrain_data.py + build_inputs.py round-trip)write_landcover_grid_json(grid, output_file_path) / load_landcover_grid_json(file_path) - Persist / reload a grid as JSONextract_river_centerlines(water_mask, world_lo, ...) - Trace river centerlines from a water mask into world-space polylinesDesign stages (each returns a result struct with a gate):
generate_roads(grid, config) - Stage 1: main + dirt road networkplace_pois(grid, roads, config) - Stage 2: villages, towns, farmsteads and other POIs along the roadsplace_fields(grid, roads, config) - Stage 3: crop fieldsplace_foliage(grid, roads, config) - Stage 4: forests, treelines, and underbrush/scrubplace_railway(grid, roads, config) - Stage 5: railway line + bridgesrun_final_pass(state) - Final gated validation across all stages before deliveryRendering (color-keyed deliverables):
render_stage_snapshot(stage, state, output_dir) - Render a cumulative Stage 1–5 PNG snapshotrender_final_deliverables(state, output_dir) - Render the combined map, foliage heatmap, and map heatmap (with the authoritative color key)Orchestrators (one-call pipelines):
run_full_pipeline(grid, config) - Run Stages 1–5 + Final Pass + all renders from a prepared gridrun_full_pipeline_for_landscape(landscape_label, config) - Stage 0 → full pipeline straight from a landscape actorMaterialization (Phase 2 — plan → level geometry):
materialize_roads_as_splines(roads, landscape_label) - Bake the road network into landscape splinesmaterialize_fields_as_paint(fields, landscape_label, layer) - Paint field regions onto a weight layermaterialize_pois_as_actors(pois, folder_path, ...) - Spawn POI marker/boundary actorsmaterialize_forest_as_foliage(foliage, forest_ft, treeline_ft, scrub_ft) - Scatter forest, treeline, and scrub foliage typesmaterialize_railway_and_bridges(railway, landscape_label, ...) - Lay the railway spline and place bridge meshesimport unreal
S = unreal.MapBlockoutService
# Phase 1 — design + validate the plan (no engine geometry yet)
cfg = unreal.MapBlockoutConfig()
cfg.level_name = "Verkhova"
cfg.layers.crop, cfg.layers.forest, cfg.layers.flood = "Crop", "Forest", "Water"
result = S.run_full_pipeline_for_landscape("Landscape1", cfg)
if not result.success:
print(result.error_message) # inspect result.final_state.<stage>.gate.checks
else:
print("Wrote:", result.output_files)
# Phase 2 — materialize the validated plan into the level
S.materialize_roads_as_splines(result.final_state.stage1_roads, "Landscape1")
S.materialize_fields_as_paint(result.final_state.stage3_fields, "Landscape1", "Crop")
S.materialize_pois_as_actors(result.final_state.stage2_pois, "/MapBlockout/POIs/")
S.materialize_forest_as_foliage(result.final_state.stage4_foliage,
"/Game/Foliage/FT_Forest", "/Game/Foliage/FT_Treeline", "/Game/Foliage/FT_Scrub")
S.materialize_railway_and_bridges(result.final_state.stage5_railway, "Landscape1")
FoliageService provides foliage type management, instance scattering, layer-aware placement, and instance queries:
Discovery:
list_foliage_types() - List all foliage types in the current levelget_instance_count(foliage_type) - Get total instance count for a foliage typeFoliage Type Management:
create_foliage_type(mesh, name, path) - Create a new FoliageType asset from a static meshget_foliage_type_property(type, property) - Get a foliage type property valueset_foliage_type_property(type, property, value) - Set a foliage type property valueScatter Placement:
scatter_foliage(type, center, radius, count) - Scatter instances in a circular areascatter_foliage_rect(type, min, max, density) - Scatter in a rectangular regionadd_foliage_instances(type, transforms) - Add instances at specific transformsscatter_foliage_on_layer(type, landscape, layer, ...) - Place foliage weighted by a landscape paint layerRemoval:
remove_foliage_in_radius(type, center, radius) - Remove instances within a radiusremove_all_foliage_of_type(type) - Remove all instances of a foliage typeclear_all_foliage() - Remove all foliage instances from the levelQuery:
get_foliage_in_radius(type, center, radius) - Get instance locations within a radiusExistence Checks:
foliage_type_exists(type) / has_foliage_instances(type) - Existence checksLifecycle:
create_system(name, path, template) - Create new Niagara systemcompile_system(path) / compile_with_results(path) - Compile with error messagessave_system(path) - Save to diskopen_in_editor(path) - Open in Niagara EditorInformation & Discovery:
get_system_info(path) - Comprehensive system informationget_system_properties(path) - Effect type, determinism, warmup, boundssummarize(path) - AI-friendly system summarylist_emitters(path) - List all emittersget_all_editable_settings(path) - Discover ALL editable settings (user params, system scripts, emitter scripts)Emitter Management:
add_emitter(system, emitter_asset, name) - Add emitter to systemcopy_emitter(src_system, src_emitter, target_system, new_name) - Copy between systemsduplicate_emitter(system, source, new_name) - Duplicate within systemremove_emitter(system, emitter) - Remove emitterrename_emitter(system, current, new) - Rename emitterenable_emitter(system, emitter, enabled) - Enable/disablemove_emitter(system, emitter, index) - Reorder emitterget_emitter_graph_position(system, emitter) - Get emitter position in graphset_emitter_graph_position(system, emitter, x, y) - Set emitter positionget_emitter_lifecycle(system, emitter) - Get loop behavior and lifecycleParameter Management:
list_parameters(path) - List user-exposed parametersget_parameter(path, name) - Get parameter value (searches User → System scripts → Emitter scripts)set_parameter(path, name, value) - Set parameter value (searches User → System scripts → Emitter scripts)add/remove_user_parameter(...) - Add/remove user parameterslist_rapid_iteration_params(system, emitter) - List emitter module parametersset_rapid_iteration_param(system, emitter, name, value) - Set module values (color, spawn rate, etc.)set_rapid_iteration_param_by_stage(...) - Set parameter in specific script stageSearch & Utilities:
search_systems(path, filter) - Find Niagara systemssearch_emitter_assets(path, filter) - Find emitter assetslist_emitter_templates(path, filter) - List available emitter templatessystem_exists(path) / emitter_exists(system, emitter) / parameter_exists(...) - Existence checkscompare_systems(source, target) - Compare two systemscopy_system_properties(target, source) - Copy system settingsdebug_activation(path) - Debug why system isn't playingModule Management:
list_modules(system, emitter, type) - List all modulesget_module_info(system, emitter, module) - Get module detailsadd_module(system, emitter, script, type) - Add moduleremove_module(system, emitter, module) - Remove moduleenable_module(system, emitter, module, enabled) - Enable/disable moduleset_module_input(system, emitter, module, input, value) - Set module inputget_module_input(system, emitter, module, input) - Get module input valuereorder_module(system, emitter, module, index) - Reorder moduleRenderer Management:
list_renderers(system, emitter) - List renderersget_renderer_details(system, emitter, index) - Get renderer detailsadd_renderer(system, emitter, type) - Add renderer (Sprite, Mesh, Ribbon, Light, Component)remove_renderer(system, emitter, index) - Remove rendererenable_renderer(system, emitter, index, enabled) - Enable/disable rendererset_renderer_property(system, emitter, index, property, value) - Set renderer propertyScript Discovery:
search_module_scripts(filter, type) - Find module scriptslist_builtin_modules(type) - List built-in modulesget_script_info(path) - Get script asset infoEmitter Properties:
get_emitter_properties(system, emitter) - Get lifecycle and property infoget_rapid_iteration_parameters(system, emitter, type) - Get rapid iteration parametersAuthors scratch-pad module graphs from Python without an open editor. NiagaraEmitterService can list/add stack modules; NiagaraScratchPadService reaches inside a scratch module to build its node graph - Map Get reads, Map Set writes, math (UNiagaraNodeOp), Custom HLSL with typed input/output pins, and schema-validated pin connections.
Module lifecycle:
create_scratch_module(system, emitter, stage, name) - Create an empty scratch module on a stageget_scratch_script_path(system, emitter, module) - Resolve the backing scratch UNiagaraScript's object pathlist_scratch_modules(system, emitter) - List all scratch modules across the emitter's stacksGraph inspection:
list_nodes(system, emitter, module) - List nodes in the scratch graphget_node_pins(system, emitter, module, node_id) - Get a node's input/output pinslist_connections(system, emitter, module) - List all wiresNode authoring:
add_node(system, emitter, module, node_type, x, y) - Create MapGet/MapSet/If/Input nodesadd_op_node(system, emitter, module, op_name, x, y) - Create a math op node (e.g. Numeric::Multiply)add_custom_hlsl_node(system, emitter, module, code, x, y) - Create a Custom HLSL node with codeset_custom_hlsl_code(system, emitter, module, node_id, code) - Replace HLSL bodyget_custom_hlsl_code(system, emitter, module, node_id) - Read HLSL bodyadd_pin(system, emitter, module, node_id, direction, type, name) - Add a typed pin (Custom HLSL via RequestNewTypedPin, MapGet/Set via AddParameterPin)delete_node(system, emitter, module, node_id)set_node_position(system, emitter, module, node_id, x, y)Wiring:
connect_pins(system, emitter, module, from_node, from_pin, to_node, to_pin) - Validated through UEdGraphSchema_Niagara::TryCreateConnectiondisconnect_pin(system, emitter, module, node_id, pin_name)Module signature helpers:
add_module_input(system, emitter, module, input_name, type) - Adds Module.<name> to the Map Get (creating it if needed). Exposes the input on the stack.add_module_output(system, emitter, module, output_name, type) - Adds a write to the Map Set.Apply:
apply_changes(system_path) - Refreshes every scratch-referencing stack module, rebuilds emitter nodes, recompiles, and saves. Call once at the end of a batch of edits.See the niagara-emitters skill for an end-to-end example that builds a Custom-HLSL splat module.
ScreenshotService enables AI vision by capturing editor content:
capture_editor_window(path) - Capture entire editor window (works for blueprints, materials, etc.)capture_viewport(path, width, height) - Capture level viewportcapture_active_window(path) - Capture foreground windowget_open_editor_tabs() - List open editor tabs with asset infoget_active_window_title() - Get focused window titleis_editor_window_active() - Check if editor is in focusViewportService provides direct control of the active Unreal Editor level viewport:
get_viewport_info() - Get camera transform, viewport type, FOV, clip planes, exposure, layout, realtime/game view flags, and camera speedset/get_viewport_type(type) - Switch between perspective, top, bottom, left, right, front, and backset/get_view_mode(mode) - Control rendering mode: lit, unlit, wireframe, detaillighting, lightingonly, lightcomplexity, shadercomplexity, pathtracing, clayset/get_fov(degrees) - Read and set perspective FOVset_near_clip_plane(distance) / set_far_clip_plane(distance) - Adjust clipping planes for close-up or large-scene workset_exposure(fixed, ev100) / set_exposure_game_settings() - Toggle fixed exposure or return to game settings / auto exposureset_game_view(enable) - Toggle editor icon and gizmo visibilityset_allow_cinematic_control(enable) - Allow Sequencer to take over the viewport cameraset_realtime(enable) - Toggle realtime renderingset_camera_location(vector) / set_camera_rotation(rotator) / set_camera_speed(speed) - Position and tune the editor cameraset/get_viewport_layout(name) - Switch between OnePane, TwoPanesHoriz, TwoPanesVert, ThreePanesLeft, ThreePanesRight, ThreePanesTop, ThreePanesBottom, FourPanesLeft, FourPanesRight, FourPanesTop, FourPanesBottom, and FourPanes2x2 / Quadimport unreal
# Inspect the active viewport
info = unreal.ViewportService.get_viewport_info()
print(info.viewport_type, info.fov, info.layout)
# Switch to quad view, then put the focused pane in top view
unreal.ViewportService.set_viewport_layout("Quad")
unreal.ViewportService.set_viewport_type("top")
# Return to perspective with fixed exposure for look-dev
unreal.ViewportService.set_viewport_type("perspective")
unreal.ViewportService.set_fov(60.0)
unreal.ViewportService.set_exposure(True, 1.0)
unreal.ViewportService.set_view_mode("lit")
RuntimeVirtualTextureService manages RVT assets and landscape integration:
create_runtime_virtual_texture(name, path, ...) - Create a Runtime Virtual Texture assetget_runtime_virtual_texture_info(path) - Get RVT asset metadatacreate_rvt_volume(landscape, rvt_path, ...) - Create an RVT volume actor sized to a landscapeassign_rvt_to_landscape(landscape, rvt_path) - Assign an RVT asset to a landscape actorProjectSettingsService provides access to project configuration and editor preferences:
list_settings_categories() - List all available settings categorieslist_settings(category) - List settings in a categoryget_setting(category, setting) - Get current setting valueset_setting(category, setting, value) - Modify setting valueget_editor_style() - Get editor UI appearance settings (toolbar icons, scale, colors)set_editor_style(property, value) - Modify editor appearance (SmallToolBarIcons, ApplicationScale, etc.)get_project_info() - Get project metadata (name, version, description)set_project_info(property, value) - Update project metadataget_default_maps() - Get editor/game startup map settingsset_default_maps(editor_map, game_map) - Configure startup mapsEngineSettingsService controls core engine configuration across multiple domains:
Rendering Settings:
get/set_rendering_setting(setting, value) - Configure rendering optionslist_rendering_settings() - List available rendering settingsPhysics Settings:
get/set_physics_setting(setting, value) - Configure physics simulationlist_physics_settings() - List available physics settingsAudio Settings:
get/set_audio_setting(setting, value) - Configure audio systemlist_audio_settings() - List available audio settingsConsole Variables (CVars):
get_cvar(name) - Get console variable valueset_cvar(name, value) - Set console variable (runtime changes)list_cvars(filter) - Search available console variablesScalability Settings:
get_scalability_level(category) - Get quality level (ViewDistance, AntiAliasing, etc.)set_scalability_level(category, level) - Set quality level (0-4: Low to Epic)get_scalability_settings() - Get all current scalability levelsapply_scalability_preset(preset) - Apply preset (Low, Medium, High, Epic, Cinematic)Garbage Collection:
get/set_gc_setting(setting, value) - Configure garbage collection behaviorlist_gc_settings() - List available GC settingsSoundCueService provides full SoundCue graph authoring — create assets, add audio nodes, wire connections, control volume/pitch/attenuation, and import SoundWave files:
Asset Lifecycle:
create_sound_cue(path, wave_path) - Create a new SoundCue (empty or with initial WavePlayer)duplicate_sound_cue(src_path, dst_path) - Copy a cue to a new pathdelete_sound_cue(path) - Delete the asset from diskget_sound_cue_info(path) - Get node count, root index, volume, pitch, durationsave_sound_cue(path) - Save to diskNode Creation (14 node types):
add_wave_player_node(path, wave_path, x, y) - Leaf node that plays a SoundWaveadd_random_node(path, x, y) - Randomly selects one childadd_mixer_node(path, num_inputs, x, y) - Blends children in paralleladd_concatenator_node(path, num_inputs, x, y) - Plays children in sequenceadd_modulator_node(path, x, y) - Random pitch/volume varianceadd_attenuation_node(path, x, y) - Spatial attenuationadd_looping_node(path, x, y) - Loops its childadd_delay_node(path, x, y) - Delay before playingadd_switch_node(path, x, y) - Routes by integer parameteradd_enveloper_node(path, x, y) - Volume/pitch envelope over timeadd_distance_cross_fade_node(path, num_inputs, x, y) - Crossfades by distanceadd_branch_node(path, x, y, bool_param) - Routes by bool parameteradd_param_cross_fade_node(path, num_inputs, x, y) - Crossfades by float paramadd_quality_level_node(path, x, y) - One input per quality levelNode Management:
list_nodes(path) - List all nodes with index, class, children, root statusconnect_nodes(path, parent, child, slot) - Wire child audio into parentdisconnect_node(path, parent_index, slot) - Break a single input linkset_root_node(path, index) - Set cue output nodeset_wave_player_asset(path, index, wave_path) - Reassign wave on existing noderemove_node(path, index) - Delete a node from the graphmove_node(path, index, x, y) - Reposition a nodeget_node_property(path, index, prop_name) - Read any node UPROPERTYset_node_property(path, index, prop_name, value) - Write any node UPROPERTYCue-Level Settings:
set_volume_multiplier(path, vol) - Set volumeset_pitch_multiplier(path, pitch) - Set pitchset_sound_class(path, class_path) - Set sound classset_attenuation(path, att_path) - Set attenuation (empty to clear)get_attenuation(path) - Get current attenuation asset pathset_concurrency(path, conc_path, clear) - Set concurrency settingsget_concurrency(path) - List assigned concurrency assetsSoundWave Utilities:
get_sound_wave_info(sw_path) - Get duration, sample rate, channels, looping, streamingimport_sound_wave(file_path, asset_path) - Import .wav/.mp3 from diskset_sound_wave_property(sw_path, prop, value) - Set any SoundWave UPROPERTYMetaSoundService provides programmatic MetaSound Source asset creation and editing — add DSP nodes, wire audio pins, manage graph I/O for runtime-parameterisable procedural audio:
Lifecycle:
create_meta_sound(package_path, asset_name, output_format) - Create a new MetaSound Source assetdelete_meta_sound(asset_path) - Delete a MetaSound assetget_meta_sound_info(asset_path) - Get node count, output format, graph I/O namessave_meta_sound(asset_path) - Save after editsNode Discovery:
list_available_nodes(search_filter) - List all registered DSP node classes with pin infoNode Management:
add_node(asset_path, namespace, name, variant, major_version, pos_x, pos_y) - Add a node by classremove_node(asset_path, node_id) - Remove node and all its edgeslist_nodes(asset_path) - List all nodes in the graphget_node_pins(asset_path, node_id) - Get pin info for a single nodeConnections:
connect_nodes(asset_path, from_node_id, output_name, to_node_id, input_name) - Connect output pin to input pindisconnect_pin(asset_path, node_id, input_name) - Remove connection to an input pinGraph I/O:
add_graph_input(asset_path, input_name, data_type, default_value) - Add a runtime parameter inputadd_graph_output(asset_path, output_name, data_type) - Add a named outputremove_graph_input(asset_path, input_name) - Remove a graph inputremove_graph_output(asset_path, output_name) - Remove a graph outputNode Configuration:
set_node_input_default(asset_path, node_id, input_name, value, data_type) - Set literal default on a node inputset_node_location(asset_path, node_id, pos_x, pos_y) - Update editor positionStateTreeService provides full programmatic control over StateTree assets: creation, state hierarchy, state type and linked-state configuration, non-destructive state reparenting, tasks, evaluators, conditions, transitions, parameters, theme colors, component overrides, property bindings, utility AI considerations (constants, weights, evaluator setup), and compilation.
Discovery & Info:
list_state_trees(directory_path) - List all StateTree assets under a content pathget_state_tree_info(asset_path) - Get full structural info (states, tasks, transitions, parameters, compile status)get_available_task_types() - List all registered task struct namesget_available_evaluator_types() - List all registered evaluator struct namesget_available_condition_types() - List all registered condition struct namesAsset Creation:
create_state_tree(asset_path, schema_class_name) - Create a new StateTree asset (schema: StateTreeComponentSchema, StateTreeAIComponentSchema, etc.)State Management:
add_state(asset_path, parent_path, state_name, state_type) - Add a state ("State", "Group", "Subtree", "Linked", "LinkedAsset")move_state(asset_path, state_path, new_parent_path, new_index) - Reparent an existing state in-place without losing its dataremove_state(asset_path, state_path) - Remove a state and all its childrenrename_state(asset_path, state_path, new_name) - Rename a stateset_state_enabled(asset_path, state_path, enabled) - Enable or disable a stateset_state_type(asset_path, state_path, state_type) - Change a state's type in place ("State", "Group", "Subtree", "Linked", "LinkedAsset")set_linked_subtree(asset_path, state_path, subtree_name) - Configure which local subtree a Linked state referencesset_linked_asset(asset_path, state_path, linked_asset_path) - Configure which external StateTree asset a LinkedAsset state referencesset_state_description(asset_path, state_path, description) - Set editor descriptionset_state_tag(asset_path, state_path, gameplay_tag) - Set gameplay tag (pass empty to clear)set_state_weight(asset_path, state_path, weight) - Set utility weight for utility-based selectionset_state_expanded(asset_path, state_path, expanded) - Expand or collapse in editor tree viewselect_state(asset_path, state_path) - Highlight a state in the open StateTree editor panelset_context_actor_class(asset_path, actor_class_path) - Set ContextActorClass on the schemaUse move_state when the intent is to move or reparent an existing StateTree state. Do not emulate a move with remove_state plus add_state, because that recreates the state instead of preserving its existing identity and attached data.
Use set_state_type, set_linked_subtree, and set_linked_asset for in-place StateTree type/link edits. Do not emulate those operations by deleting and recreating states.
State Properties:
set_selection_behavior(asset_path, state_path, behavior) - How children are selected (TrySelectChildrenInOrder, TrySelectChildrenAtRandom, etc.)set_tasks_completion(asset_path, state_path, completion) - Task completion mode: "Any" or "All"Theme Colors:
get_theme_colors(asset_path) - List all named theme colors and which states use themset_state_theme_color(asset_path, state_path, color_name, color) - Assign a named color to a staterename_theme_color(asset_path, old_color_name, new_color_name) - Rename a color entryParameters:
get_root_parameters(asset_path) - Get all root parameters (name, type, default value)add_or_update_root_parameter(asset_path, name, type, default_value) - Add/update a parameter ("Bool", "Int32", "Float", "Double", "String", etc.)add_or_update_root_float_parameter(asset_path, parameter_name, default_value) - Convenience: add/update a float parameterremove_root_parameter(asset_path, name) - Remove a parameter by namerename_root_parameter(asset_path, old_name, new_name) - Rename a parameterLevel Actor Component Overrides:
get_component_state_tree_path(actor_name_or_label) - Get the StateTree asset used by a placed actor's StateTreeComponentget_component_parameter_overrides(actor_name_or_label) - Inspect current per-instance parameter override values on a placed actorset_component_parameter_override(actor_name_or_label, parameter_name, value) - Set a per-instance parameter override on a placed actor's StateTreeComponentTasks:
add_task(asset_path, state_path, task_struct_name) - Add a task by C++ struct name (e.g. "FStateTreeDelayTask")remove_task(asset_path, state_path, task_struct_name, task_match_index) - Remove a taskmove_task(asset_path, state_path, task_struct_name, task_match_index, new_index) - Reorder a taskset_task_enabled(asset_path, state_path, task_struct_name, task_match_index, enabled) - Enable/disable a taskset_task_considered_for_completion(asset_path, state_path, task_struct_name, task_match_index, considered) - Whether task counts toward state completionget_task_property_names(asset_path, state_path, task_struct_name, task_match_index) - Discover all editable task propertiesget_task_property_value(asset_path, state_path, task_struct_name, property_path, task_match_index) - Read a task property valueset_task_property_value(asset_path, state_path, task_struct_name, property_path, value, task_match_index) - Set a task property valueset_task_property_value_detailed(...) - Set task property with structured result (failure reason + readback value)bind_task_property_to_root_parameter(asset_path, state_path, task_struct_name, task_property_path, parameter_path, task_match_index) - Bind task property to a root parameterbind_task_property_to_context(asset_path, state_path, task_struct_name, task_property_path, context_name, context_property_path, task_match_index) - Bind task property to context databind_task_property_to_global_task_property(asset_path, state_path, task_struct_name, task_property_path, global_task_struct_name, global_task_property_path, task_match_index, global_task_match_index) - Bind a state task property to a property on a global taskunbind_task_property(asset_path, state_path, task_struct_name, task_property_path, task_match_index) - Remove a task property bindingEvaluators & Global Tasks:
add_evaluator(asset_path, evaluator_struct_name) - Add a global evaluatorremove_evaluator(asset_path, evaluator_struct_name, match_index) - Remove an evaluatorget_evaluator_property_names(asset_path, evaluator_struct_name, match_index) - Get evaluator propertiesset_evaluator_property_value(asset_path, evaluator_struct_name, property_path, value, match_index) - Set evaluator propertybind_evaluator_property_to_root_parameter(asset_path, evaluator_struct_name, evaluator_property_path, parameter_path, match_index) - Bind evaluator property to a root parameterbind_evaluator_property_to_context(asset_path, evaluator_struct_name, evaluator_property_path, context_name, context_property_path, match_index) - Bind evaluator property to context dataunbind_evaluator_property(asset_path, evaluator_struct_name, evaluator_property_path, match_index) - Remove an evaluator property bindingadd_global_task(asset_path, task_struct_name) - Add a global taskremove_global_task(asset_path, task_struct_name, match_index) - Remove a global taskget_global_task_property_names(asset_path, task_struct_name, match_index) - Get global task propertiesset_global_task_property_value(asset_path, task_struct_name, property_path, value, match_index) - Set global task propertybind_global_task_property_to_root_parameter(asset_path, task_struct_name, task_property_path, parameter_path, match_index) - Bind global task property to a root parameterbind_global_task_property_to_context(asset_path, task_struct_name, task_property_path, context_name, context_property_path, match_index) - Bind global task property to context dataunbind_global_task_property(asset_path, task_struct_name, task_property_path, match_index) - Remove a global task property bindingEnter Conditions:
add_enter_condition(asset_path, state_path, condition_struct_name) - Add an enter condition to a stateremove_enter_condition(asset_path, state_path, condition_index) - Remove an enter condition by indexset_enter_condition_operand(asset_path, state_path, condition_index, operand) - Set "And" / "Or" / "Copy" operandget_enter_condition_property_names(asset_path, state_path, condition_struct_name, condition_match_index) - Discover condition propertiesset_enter_condition_property_value(asset_path, state_path, condition_struct_name, property_path, value, condition_match_index) - Set a condition propertybind_enter_condition_property_to_context(asset_path, state_path, condition_struct_name, condition_property_path, context_name, context_property_path, condition_match_index) - Bind an enter condition property to context databind_enter_condition_property_to_global_task_property(asset_path, state_path, condition_struct_name, condition_property_path, global_task_struct_name, global_task_property_path, condition_match_index, global_task_match_index) - Bind an enter condition property to a property on a global taskbind_enter_condition_property_to_root_parameter(asset_path, state_path, condition_struct_name, condition_property_path, parameter_path, condition_match_index) - Bind an enter condition property to a root parameterunbind_enter_condition_property(asset_path, state_path, condition_struct_name, condition_property_path, condition_match_index) - Remove an enter condition property bindingTransitions:
add_transition(asset_path, state_path, trigger, transition_type, target_path, priority) - Add a transition ("OnStateCompleted", "GotoState", etc.)update_transition(asset_path, state_path, transition_index, ...) - Modify trigger, type, target, priority, enabled, or delay settingsbind_transition_to_delegate(asset_path, state_path, transition_index, task_struct_name, dispatcher_property_name, task_match_index) - Bind an OnDelegate transition to a task dispatcher propertyremove_transition(asset_path, state_path, transition_index) - Remove a transition by indexmove_transition(asset_path, state_path, from_index, to_index) - Reorder a transitionTransition Conditions:
add_transition_condition(asset_path, state_path, transition_index, condition_struct_name) - Add a condition to a transitionremove_transition_condition(asset_path, state_path, transition_index, condition_index) - Remove a transition conditionset_transition_condition_operand(asset_path, state_path, transition_index, condition_index, operand) - Set operandget_transition_condition_property_names(asset_path, state_path, transition_index, condition_struct_name, condition_match_index) - Discover propertiesget_transition_event_payload_property_names(asset_path, state_path, transition_index) - Discover bindable properties from an OnEvent transition's payload structset_transition_condition_property_value(asset_path, state_path, transition_index, condition_struct_name, property_path, value, condition_match_index) - Set propertybind_transition_condition_property_to_context(asset_path, state_path, transition_index, condition_struct_name, condition_property_path, context_name, context_property_path, condition_match_index) - Bind a transition condition property to context databind_transition_condition_property_to_event_payload(asset_path, state_path, transition_index, condition_struct_name, condition_property_path, payload_property_path, condition_match_index) - Bind a transition condition property to an event payload propertyunbind_transition_condition_property(asset_path, state_path, transition_index, condition_struct_name, condition_property_path, condition_match_index) - Remove a transition condition property bindingCompile & Save:
compile_state_tree(asset_path) - Compile the asset; returns success flag, errors, and warningssave_state_tree(asset_path) - Save to diskEditorTransactionService provides programmatic undo/redo and transaction management:
Undo / Redo:
undo() — Undo the last transactionredo() — Redo the last undone transactionundo_multiple(count) — Undo multiple transactions at onceredo_multiple(count) — Redo multiple transactions at onceTransaction Grouping:
begin_transaction(description) — Open a named transaction scopeend_transaction() — Close the current transaction scopecancel_transaction() — Cancel (rollback) the current transactionHistory Inspection:
can_undo() — Check if undo is availablecan_redo() — Check if redo is availableget_undo_description() — Get the description of the next undo actionget_redo_description() — Get the description of the next redo actionget_undo_history(count) — List recent undo history entriesget_redo_history(count) — List recent redo history entriesget_undo_count() — Get total number of undo entriesget_redo_count() — Get total number of redo entriesBuffer Reset:
reset_history() — Clear the entire undo/redo buffer# 1. Create blueprint
path = unreal.BlueprintService.create_blueprint("BP_Player", "Actor", "/Game/Blueprints")
# 2. Add variables
unreal.BlueprintService.add_variable(path, "Health", "Float", "100.0")
unreal.BlueprintService.add_variable(path, "MaxHealth", "Float", "100.0")
# 3. Compile (REQUIRED before adding variable nodes)
unreal.BlueprintService.compile_blueprint(path)
# 4. Save
unreal.EditorAssetLibrary.save_asset(path)
# 1. Create material
path = "/Game/Materials/M_Custom"
unreal.MaterialService.create_material("M_Custom", "/Game/Materials")
# 2. Create parameter
param_id = unreal.MaterialNodeService.create_parameter(
path, "Vector", "BaseColor", "Surface", "", -300, 0
)
# 3. Connect to output
unreal.MaterialNodeService.connect_to_output(path, param_id, "", "BaseColor")
# 4. Compile
unreal.MaterialService.compile_material(path)
# 1. Find row struct types
types = unreal.DataTableService.search_row_types("Character")
# 2. Create table
unreal.DataTableService.create_data_table("CharacterStats", "/Game/Data", "DT_Characters")
### Configure Project and Engine Settings
```python
# Configure Editor UI Appearance
unreal.ProjectSettingsService.set_editor_style("SmallToolBarIcons", "true")
unreal.ProjectSettingsService.set_editor_style("ApplicationScale", "1.2")
# Set Project Metadata
unreal.ProjectSettingsService.set_project_info("ProjectName", "My Awesome Game")
unreal.ProjectSettingsService.set_project_info("Description", "An epic adventure")
# Configure Startup Maps
unreal.ProjectSettingsService.set_default_maps(
editor_map="/Game/Levels/EditorLevel",
game_map="/Game/Levels/MainMenu"
)
# Configure Rendering Settings
unreal.EngineSettingsService.set_rendering_setting("bDefaultFeatureLevelES31", "true")
unreal.EngineSettingsService.set_rendering_setting("DefaultGraphicsRHI", "DefaultGraphicsRHI_DX12")
# Adjust Graphics Quality via Scalability
unreal.EngineSettingsService.apply_scalability_preset("High")
# Or set individual categories
unreal.EngineSettingsService.set_scalability_level("ViewDistance", 3) # 0-4: Low to Epic
unreal.EngineSettingsService.set_scalability_level("AntiAliasing", 4)
# Configure Physics Settings
unreal.EngineSettingsService.set_physics_setting("bEnableStabilization", "true")
unreal.EngineSettingsService.set_physics_setting("MaxSubsteps", "6")
# Set Console Variables (CVars) for runtime changes
unreal.EngineSettingsService.set_cvar("r.ScreenPercentage", "100")
unreal.EngineSettingsService.set_cvar("r.Bloom", "1")
# Configure Garbage Collection
unreal.EngineSettingsService.set_gc_setting("gc.MaxObjectsInGame", "2097152")
unreal.EngineSettingsService.set_gc_setting("gc.TimeBetweenPurgingPendingKillObjects", "60.0")
unreal.DataTableService.add_row("/Game/Data/DT_Characters", "Hero", '{"Name": "Hero", "Health": 100, "Damage": 25}')
row = unreal.DataTableService.get_row("/Game/Data/DT_Characters", "Hero")
### Build Animation Montage with Multiple Animations
```python
# 1. Create empty montage from skeleton
path = unreal.AnimMontageService.create_empty_montage(
"/Game/Characters/Mannequin/SK_Mannequin",
"/Game/Montages",
"AM_ComboAttack"
)
# 2. Add animation segments sequentially
unreal.AnimMontageService.add_anim_segment(path, 0, "/Game/Animations/Attack1", 0.0)
unreal.AnimMontageService.add_anim_segment(path, 0, "/Game/Animations/Attack2", 1.0)
unreal.AnimMontageService.add_anim_segment(path, 0, "/Game/Animations/Attack3", 2.0)
# 3. Add sections for each attack phase
unreal.AnimMontageService.add_section(path, "Attack1", 0.0)
unreal.AnimMontageService.add_section(path, "Attack2", 1.0)
unreal.AnimMontageService.add_section(path, "Attack3", 2.0)
# 4. Link sections for combo flow
unreal.AnimMontageService.set_next_section(path, "Attack1", "Attack2")
unreal.AnimMontageService.set_next_section(path, "Attack2", "Attack3")
# 5. Add branching points for combo input windows
unreal.AnimMontageService.add_branching_point(path, "ComboWindow1", 0.7)
unreal.AnimMontageService.add_branching_point(path, "ComboWindow2", 1.7)
# 6. Set blend settings
unreal.AnimMontageService.set_blend_in(path, 0.15, "Cubic")
unreal.AnimMontageService.set_blend_out(path, 0.2, "Linear")
# 7. Refresh editor to see changes
unreal.AnimMontageService.refresh_montage_editor(path)
# 8. Save
unreal.EditorAssetLibrary.save_asset(path)
# 1. Create system
result = unreal.NiagaraService.create_system("NS_Fire", "/Game/VFX")
path = result.asset_path
# 2. Add emitters
unreal.NiagaraService.add_emitter(path, "minimal", "Flames")
unreal.NiagaraService.add_emitter(path, "minimal", "Smoke")
# 3. Discover ALL editable settings (recommended first step for existing systems)
settings = unreal.NiagaraService.get_all_editable_settings(path)
print(f"Total settings: {settings.total_settings_count}")
# User Parameters (top priority)
for p in settings.user_parameters:
print(f"[User] {p.setting_path} ({p.value_type}): {p.current_value}")
# System & Emitter script settings
for p in settings.rapid_iteration_parameters:
if "Color" in p.setting_path:
print(f"[{p.emitter_name}] {p.setting_path}: {p.current_value}")
# 4. Set parameters (searches User → System scripts → Emitter scripts)
unreal.NiagaraService.set_parameter(path, "User.Color", "(R=1,G=0.5,B=0,A=1)")
unreal.NiagaraService.set_parameter(path, "System.Color", "(R=3,G=0.5,B=0,A=1)")
# 5. Set rapid iteration parameters (emitter-specific)
unreal.NiagaraService.set_rapid_iteration_param(
path, "Flames",
"Constants.Flames.SpawnRate.SpawnRate",
"500.0"
)
# 6. Compile and save
unreal.NiagaraService.compile_system(path)
unreal.NiagaraService.save_system(path)
# 1. Geocode a place name to get GPS coordinates
# MCP: deep_research(action="geocode", query="Mount Fuji")
# → lat=35.3606, lng=138.7274
# 2. Preview elevation to get suggested settings
# MCP: terrain_data(action="preview_elevation", lng=138.7274, lat=35.3606)
# → suggested_base_level=340, suggested_height_scale=27
# 3. Generate heightmap matching your landscape resolution
# MCP: terrain_data(
# action="generate_heightmap",
# lng=138.7274, lat=35.3606,
# base_level=340, height_scale=27,
# resolution=1009, format="png"
# )
# → file="C:/Project/Saved/Terrain/heightmap_35.3606_138.7274.png"
# 4. Create landscape and import heightmap
path = unreal.LandscapeService.create_landscape("MtFuji",
num_components_x=16, num_components_y=16,
quads_per_section=63, sections_per_component=1)
unreal.LandscapeService.import_heightmap("MtFuji",
"C:/Project/Saved/Terrain/heightmap_35.3606_138.7274.png")
# 5. Optionally get a satellite reference image
# MCP: terrain_data(action="get_map_image", lng=138.7274, lat=35.3606, style="satellite-v9")
Connect VS Code, Claude Code, Cursor, or AntiGravity to control Unreal via MCP.
In Project Settings > Plugins > VibeUE:
| Setting | Default | Description |
|---|---|---|
| Enable MCP Server | Enabled | Toggle HTTP server |
| Port | 8088 | MCP endpoint port |
| Bearer Token | (empty) | MCP clients must send this as Authorization: Bearer <token>. Leave empty to allow unauthenticated connections. |
Server runs at http://127.0.0.1:8088/mcp
⚠️ VibeUE API Key required: The MCP server validates your VibeUE API Key (set in the AI Chat settings) against
vibeue.comat startup. All MCP tool calls will fail with an error until a valid key is configured. Get your free key at vibeue.com/login.
Create .vscode/mcp.json:
{
"servers": {
"VibeUE": {
"type": "http",
"url": "http://127.0.0.1:8088/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
Run once in your terminal:
claude mcp add --scope user --transport stdio VibeUE-Claude -- npx -y mcp-remote http://127.0.0.1:8088/mcp --transport http-only --allow-http --header "Authorization:Bearer YOUR_API_KEY"
Omit the --header arguments if no API key is set in VibeUE.
{
"mcpServers": {
"VibeUE": {
"type": "http",
"url": "http://127.0.0.1:8088/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}
The proxy is optional and runs on http://127.0.0.1:8089/mcp.
Use it when you want:
Authorization header managementAuthorization headers per-requestCreate Plugins/VibeUE/vibeue-proxy.json:
{
"bearer_token": "YOUR_API_KEY"
}
YOUR_API_KEY must match Project Settings > Plugins > VibeUE > API Key.
# Windows (silent background process — interactive shells / Explorer)
Start-Process -FilePath 'pythonw.exe' -ArgumentList 'Plugins/VibeUE/Content/Python/vibeue-proxy.py' -WindowStyle Hidden
AI agent / headless shells (Claude Code, Cursor, Windsurf):
pythonwandstart /Bfail silently in headless contexts — errors are swallowed and the proxy never starts. Usepythondirectly instead:hljs language-bash# Windows — AI agent / headless shell python Plugins/VibeUE/Content/Python/vibeue-proxy.py &
# Mac / Linux
python3 Plugins/VibeUE/Content/Python/vibeue-proxy.py &
The proxy survives session close. Once started, it keeps running until the machine restarts or it is killed manually — no need to restart it each AI session.
Optional Windows auto-start: add a shortcut to Plugins/VibeUE/Content/Python/start-vibeue-proxy.bat in shell:startup. The bat kills any existing proxy instance before starting a fresh one, so it is safe to re-run if something goes wrong.
VS Code .vscode/mcp.json:
{
"servers": {
"VibeUE": {
"type": "http",
"url": "http://127.0.0.1:8089/mcp"
}
}
}
Claude Code:
claude mcp add --scope user --transport stdio VibeUE-Claude -- npx -y mcp-remote http://127.0.0.1:8089/mcp --transport http-only --allow-http
Cursor / AntiGravity:
{
"mcpServers": {
"VibeUE": {
"type": "http",
"url": "http://127.0.0.1:8089/mcp"
}
}
}
The proxy injects the token from vibeue-proxy.json when forwarding requests to Unreal.
Verify the proxy is running before wiring up your MCP client:
# Windows
netstat -ano | findstr :8089
# Mac / Linux
lsof -i :8089
A LISTENING result on port 8089 confirms the proxy is up. If nothing appears, check that vibeue-proxy.json exists and Python is on your PATH.
Add project-specific context in Plugins/VibeUE/Content/instructions/:
# Project: My Game
## Naming Conventions
- Blueprints: BP_<Type>_<Name>
- Widgets: WBP_<Name>
- Materials: M_<Surface>_<Variant>
All .md files in this directory are automatically concatenated and loaded as AI context.
The system prompt supports dynamic token replacement. When the instructions are loaded, certain tokens are replaced with dynamically generated content:
| Token | Replacement | Source |
|---|---|---|
{SKILLS} | Skills table with names, descriptions, and services | Scanned from Content/Skills/*/SKILL.md frontmatter |
Example usage in vibeue.instructions.md:
## Available Skills
Load skills using `vibeue-skills-manager(action="load", skill_name="<name>")`:
{SKILLS}
Generated output:
| Skill | Description | Services |
|-------|-------------|----------|
| `blueprints` | Create and modify Blueprint assets... | BlueprintService, AssetDiscoveryService |
| `materials` | Create and edit materials... | MaterialService, MaterialNodeService |
...
This allows the skills list to stay in sync automatically when skills are added, removed, or modified. Each skill's metadata is defined in its SKILL.md YAML frontmatter:
---
name: blueprints
display_name: Blueprint System
description: Create and modify Blueprint assets, variables, functions, components, and node graphs
vibeue_classes:
- BlueprintService
- AssetDiscoveryService
---
The in-editor chat can connect to additional MCP servers via Config/vibeue.mcp.json.
Both stdio and http transports are supported:
{
"servers": {
"unreal-engine-skills": {
"type": "http",
"url": "https://www.unrealengineskills.com/api/mcp"
},
"my-tool": {
"type": "stdio",
"command": "python",
"args": ["-m", "my_mcp_tool"]
}
}
}
VibeUE ships preconfigured with the Unreal Engine Skills
MCP server (unreal-engine-skills-manager tool) — a UE 5.7 domain-knowledge library: correct
engine APIs, architecture patterns, best practices, and engine-source citations.
The two skill systems complement each other:
Brains — unreal-engine-skills-manager | Hands — vibeue-skills-manager | |
|---|---|---|
| Answers | WHAT to build and WHY (engine knowledge, best practices) | HOW to execute it in the editor (service workflows, formats) |
| Touches the editor? | No — knowledge only | Yes — via VibeUE services |
The system prompt instructs the AI to consult the Brains library before design, review, or "best practices" questions, then use VibeUE skills to do the editor work. If the external server is unreachable, the chat falls back to VibeUE skills alone.
# DON'T guess APIs - discover them
# MCP: discover_python_class("unreal.BlueprintService")
add_variable(path, "Health", "Float")
compile_blueprint(path) # REQUIRED!
add_get_variable_node(path, graph, "Health", 0, 0) # Now works
# CORRECT
"/Game/Blueprints/BP_Player"
# WRONG
"BP_Player"
Avoid: modal dialogs, input(), long time.sleep(), infinite loops
Plugins/VibeUE/
├── Source/VibeUE/
│ ├── Public/PythonAPI/ # Python service headers
│ └── Private/PythonAPI/ # Python service implementations
├── Config/
│ ├── Instructions/ # Custom instruction files
│ └── vibeue.mcp.json # External MCP servers
├── Content/
│ ├── instructions/ # AI system prompts
│ └── samples/ # Ready-made AI assistant instruction templates
└── VibeUE.uplugin
MIT License — Copyright © 2025 Kevin Buckley / Buckley Builds LLC
This project is open source and freely available under the MIT License. You may use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, subject to the license terms.
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
mcp-language-server gives MCP enabled clients access semantic tools like get definition, references, rename, and diagnos
Browser automation using accessibility snapshots instead of screenshots
MCP server integration for DaVinci Resolve Studio