Level¶
127 tools. Back to the index.
add_foliage_instances¶
Destructive.
Place foliage instances of a UFoliageType at explicit transforms in the level's InstancedFoliageActor. DANGER: measured CRASHING the editor process (access violation inside UnrealEditor-FoliageEdit.dll) -- reproducibly, and a single instance crashes just like a thousand, so trimming the count does not help. The reply you see is a "Connection reset", which reads like a network hiccup and is not. Use add_instanced_static_mesh_component + add_ism_instance instead: an InstancedFoliageActor is itself an actor holding instanced-static-mesh components, so it is the same code path minus the crash. Save your work before calling this at all.
| Parameter | Type | Required | Description |
|---|---|---|---|
foliage_type_path |
string | yes | Full path of the UFoliageType asset |
transforms |
array | yes | List of [x,y,z] locations or objects with location, rotation, scale |
Returns: { foliage_type_path: string, foliage_type: string, requested: int, instances_added: int, instance_count_before: int, instance_count: int, placed_instance_count: int, instances_added_ok: bool, foliage_actor: string }
add_height_mask_node¶
Additive.
Drop the nodes of an altitude mask into a material graph: a SmoothStep preset with ConstMin=min_height / ConstMax=max_height in world units, for blending a layer in by height (snow above a line, sand below one). It does NOT build a wired chain despite the name: the SmoothStep Value input is left UNCONNECTED and no world-position node is wired, so you must connect WorldPosition Z into it yourself (connect_material_expressions) or the mask stays constant. Use the reply's expression_id and note to find the pin, then re-read the graph as the oracle.
| Parameter | Type | Required | Description |
|---|---|---|---|
material_path |
string | yes | Asset path of the target UMaterial |
min_height |
number | yes | Lower bound (world units) for SmoothStep. Below this the mask is 0. |
max_height |
number | yes | Upper bound (world units) for SmoothStep. Above this the mask is 1. |
pos_x |
string | no | Editor graph X position of the SmoothStep output (default -800) |
pos_y |
string | no | Editor graph Y position of the SmoothStep output (default 0) |
Returns: { material_path, expression_id (the SmoothStep node), min_height, max_height }
add_landscape_layer¶
Additive.
Register a LandscapeLayerInfo asset as a target weight (paint) layer on a landscape, so the terrain can store weight for it and the material's LandscapeLayerBlend can read it. Step 2 of three, between create_landscape_layer_info and paint_landscape_layer -- painting a layer that was never registered writes nothing. Already-registered layers return already_present=true; remove_landscape_layer is the inverse, get_landscape_layers lists what is registered now.
| Parameter | Type | Required | Description |
|---|---|---|---|
layer_info_path |
string | yes | Full path of the ULandscapeLayerInfoObject asset |
landscape_actor_name |
string | no | Optional landscape actor name, defaults to first found |
Returns: { landscape_actor_name: string, layer_info_path: string, layer_name: string, layer_added: bool, already_present: bool, target_layer_count: int }
add_landscape_layer_blend_node¶
Additive.
Add the LandscapeLayerBlend node that makes a terrain material multi-layered, pre-populated with one input per name in layer_names (weight / alpha / height blend). This is what lets grass, rock, sand and snow coexist on one landscape material, and the layer names must match the ones registered on the terrain with add_landscape_layer or those inputs read zero weight forever. The node is created with its layer inputs but nothing feeding them -- wire each layer's texture chain with connect_material_expressions, then compile_material and check get_material_stats.
| Parameter | Type | Required | Description |
|---|---|---|---|
material_path |
string | yes | Asset path of the target UMaterial (e.g. /Game/Materials/M_Landscape) |
layer_names |
array | yes | List of FName layer names to add (in order). Each becomes a FLayerBlendInput with LB_WeightBlend. |
blend_type |
string | no | Optional "weight" (default) | "alpha" | "height" for the layer blend enum |
pos_x |
string | no | Editor graph X position (default -800) |
pos_y |
string | no | Editor graph Y position (default -200) |
Returns: { material_path, expression_id, layer_count, layers: [{layer_name, blend_type}] }
add_landscape_spline_control_point¶
Additive.
Add a control point to a landscape's spline component -- the first half of laying a road, river bed or path across the terrain (connect consecutive points with add_landscape_spline_segment). Coordinates are LANDSCAPE-LOCAL, not world: subtract the landscape's location (get_landscape_info) before passing them, or the point lands somewhere else entirely. width is a HALF-width. The reply's control_point_index is what the segment and edit tools address.
| Parameter | Type | Required | Description |
|---|---|---|---|
landscape_name |
string | no | Optional landscape actor name, defaults to first found |
location |
array | no | [x, y, z] in landscape-local space, default [0,0,0] |
width |
number | no | Half-width at this point, default 128 |
Returns: { landscape_name: string, control_point_index: int, control_point_count: int, width: number, added: bool, location: [number] }
add_landscape_spline_segment¶
Additive.
Join two existing landscape spline control points with a segment -- the second half of laying a road, river or path: points alone render nothing, the segments between them are the spline. Both indices must already exist (add_landscape_spline_control_point returns them). Chain segments point-to-point for a route; use get_landscape_splines to confirm segment_count grew.
| Parameter | Type | Required | Description |
|---|---|---|---|
start_point_index |
integer | yes | Index of the start control point |
end_point_index |
integer | yes | Index of the end control point |
landscape_name |
string | no | Optional landscape actor name, defaults to first found |
Returns: { landscape_name: string, segment_index: int, segment_count: int, start_point_index: int, end_point_index: int, added: bool }
add_light¶
Additive.
Spawn a Directional, Point, Spot, Rect or Sky light actor in the editor world (not PIE) at location and rotation, optionally setting intensity and color, outside any undo transaction; nothing is saved. Returns light_type and the internal actor_name of the new actor.
| Parameter | Type | Required | Description |
|---|---|---|---|
light_type |
string | yes | Directional, Point, Spot, Rect, or Sky (case-insensitive); anything else is an error. |
location |
array | no | [x, y, z] world location in cm; default [0, 0, 0], also when the array has fewer than 3 numbers. |
rotation |
array | no | World rotation in degrees as [pitch, yaw, roll], default [0, 0, 0]; directional, spot and rect lights shine along its forward axis. |
intensity |
number | no | Value for the Intensity property in the units of the light (Directional: lux; Sky: a multiplier); engine default when omitted. |
color |
array | no | [r, g, b] linear color, usually 0..1; default white. Any other form (an object, a hex string, fewer than 3 numbers) sets black. |
Returns: { light_type: string, actor_name: string }
add_slope_mask_node¶
Additive.
Drop the two nodes of a slope mask into a material graph: a SmoothStep preset with ConstMin=min_slope / ConstMax=max_slope, plus a downstream node whose output is the mask (intended 1 on flat ground, 0 on vertical walls). It does NOT build a wired chain despite the name: no VertexNormalWS node is created and both inputs are left UNCONNECTED, so until you wire VertexNormalWS.B into the SmoothStep Value pin yourself (connect_material_expressions) the mask evaluates to a constant. The reply's expression_id and note tell you which node to wire. Verify by re-reading the graph, not by success.
| Parameter | Type | Required | Description |
|---|---|---|---|
material_path |
string | yes | Asset path of the target UMaterial |
min_slope |
number | no | Lower bound (radians or slope units, depending on convention) for SmoothStep (default 0.0) |
max_slope |
number | no | Upper bound for SmoothStep (default 0.5) |
pos_x |
string | no | Editor graph X position (default -800) |
pos_y |
string | no | Editor graph Y position (default 200) |
Returns: { material_path, expression_id (the OneMinus output), min_slope, max_slope }
add_spline_component¶
Destructive.
Adds a USplineComponent instance to a named editor-world actor. NewObject + RegisterComponent + AddInstanceComponent + attach to root + CreationMethod=Instance. If points are given, clears the default points and adds each in local space.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Display label or internal name of the target editor-world actor |
points |
array | no | Optional [[x, y, z], ...] spline points in local space |
Returns: { actor_name: string, component_name: string, component_class: string, num_points: int, added: bool }
add_spline_mesh_component¶
Additive.
Adds a USplineMeshComponent instance to a named editor-world actor. NewObject + SetStaticMesh + RegisterComponent + AddInstanceComponent + attach to root + CreationMethod=Instance, then SetStartAndEnd to deform the mesh straight from start to end (tangent = end - start).
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Display label or internal name of the target editor-world actor |
static_mesh_path |
string | yes | /Game or /Engine path to the static mesh to deform |
start |
array | no | Optional [x, y, z] start point; defaults to (0,0,0) |
end |
array | no | Optional [x, y, z] end point; defaults to (100,0,0) |
Returns: { actor_name: string, component_name: string, component_class: string, static_mesh_path: string, mesh_set: bool, start: [number, number, number], end: [number, number, number], added: bool }
add_streaming_level¶
Additive, idempotent.
Adds a saved level package to the editor world as a streaming sub-level. Creates a ULevelStreamingDynamic wrapper referencing the given level package and attaches it to the current editor world's StreamingLevels array. The package must already exist on disk (a streaming level references a saved .umap). Idempotent: if the level is already a streaming level, returns its current state with added=false. (an object path "/Game/Maps/SubLevel.SubLevel" is also accepted).
| Parameter | Type | Required | Description |
|---|---|---|---|
level_package_path |
string | yes | Package path of the level, e.g. "/Game/Maps/SubLevel" |
should_be_loaded |
boolean | no | Desired initial ShouldBeLoaded state (optional, default true) |
should_be_visible |
boolean | no | Desired initial ShouldBeVisible state (optional, default true) |
Returns: { package_name: string, name: string, streaming_class: string, should_be_loaded: bool, should_be_visible: bool, is_level_loaded: bool, is_level_visible: bool, added: bool, already_present: bool, streaming_level_count: number }
assign_actor_to_data_layer_instance¶
Destructive.
Assigns an editor-world actor to a data layer instance. Uses UDataLayerEditorSubsystem::AddActorToDataLayer against the data layer instance referencing the given asset. Requires a World Partition world; on a non-WP (default) map this returns an honest error (no editor-world swap).
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Label or name of the actor in the editor world. |
data_layer_asset_path |
string | yes | Full /Game path to the UDataLayerAsset (must be instanced in the world first via create_data_layer_instance). |
Returns: { actor_name: string, data_layer_asset_path: string, instance_name: string, short_name: string, assigned: bool, message: string }
attach_actor¶
Destructive.
Attach one actor to another optionally at a socket keeping world transform
| Parameter | Type | Required | Description |
|---|---|---|---|
child_actor_name |
string | yes | Name or label of the child actor to attach |
parent_actor_name |
string | yes | Name or label of the parent actor to attach to |
socket_name |
string | no | Optional socket on the parent to attach to |
Returns: { child: string, parent: string, attached: bool }
break_level_instance¶
Destructive.
Breaks an ALevelInstance actor, un-nesting its sub-level content into the current editor level as plain actors and destroying the original level-instance actor. Canonical headless path: resolve the ALevelInstance by label/name, then ULevelInstanceSubsystem::CanBreakLevelInstance (gate) -> BlockLoadLevelInstance (synchronous load) -> BreakLevelInstance. CanBreakLevelInstance is checked BEFORE BlockLoadLevelInstance on purpose: BlockLoadLevelInstance asserts check(!IsEditing()) and CanBreakLevelInstance rejects the editing/level-script states, so this ordering prevents the assert. BreakLevelInstance returns false when nothing was moved (an empty sub-level is the honest broke=false case, NOT an error). The original actor is destroyed by the engine, so this is a one-shot destructive op: re-running with the same name reports "level instance not found". Requires the editor (GEditor); BreakLevelInstance touches GEditor->GetSelectedActors()/Trans unguarded.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Required. Label or name of the ALevelInstance actor to break (matched via GetActorNameOrLabel). |
levels |
number | no | Optional, default 1. How many nested levels deep to break (passed to BreakLevelInstance Levels). |
keep_folders |
boolean | no | Optional, default false. When true, preserve the source actor folders (ELevelInstanceBreakFlags::KeepFolders) instead of flattening them. |
Returns: { actor_name: string, broke: bool, moved_actor_count: number, moved_actors: [string], levels: number, keep_folders: bool, was_loaded_forced: bool, note: string }
build_lighting¶
Destructive.
Start an asynchronous static lighting build of all levels in the editor world (not only the current one) and return started without waiting for the result. Side effect: writes the quality and OnlyBuildCurrentLevel=false into LightingBuildOptions of the editor per-project settings.
| Parameter | Type | Required | Description |
|---|---|---|---|
quality |
string | no | Preview, Medium, High or Production (case-insensitive); any other value silently builds at Preview. Default Preview. |
Returns: { quality: string, started: bool, note: string }
build_minimap¶
Destructive.
Reports whether a World Partition minimap can be / has been built for the current editor world. HONEST gate: minimap generation is a GPU scene-capture / commandlet-rendering operation (FWorldPartitionMiniMapHelper::CaptureBoundsMiniMapToTexture via ASceneCapture2D, or UWorldPartitionMiniMapBuilder whose RequiresCommandletRendering()==true, both gated by -AllowCommandletRendering) and cannot be driven synchronously from a single request. The tool does the headless-safe part for real (resolves the editor world, detects World Partition, and on a WP world reads back whether a minimap texture already exists) and returns built=false with a note.
No parameters.
Returns: { world: string, is_world_partition: bool, built: bool, already_has_minimap?: bool, success: bool, note: string, message: string }
capture_pie_screenshot¶
Destructive.
Write a PNG of the game viewport (else the active editor viewport) from a synchronous ReadPixels, which omits the UMG/Slate HUD; returns output_path, width, height and bytes_written. With include_ui=true during PIE, a cropped HUD version overwrites output_path a frame later (ui_overwrite_next_frame).
| Parameter | Type | Required | Description |
|---|---|---|---|
output_path |
string | no | Optional string. If empty, auto-names into <Project>/Saved/MCP/PIE_<utc>.png. |
include_ui |
boolean | no | When true and PIE is running with rendering, also request an engine screenshot with the HUD that a later frame crops to the game viewport (editor chrome removed) and writes over output_path; SDR only, given up after 8 s. Default false. |
Returns: { saved_to_pie_active, output_path, width, height, bytes_written, includes_ui, ui_overwrite_next_frame, ui_note? }
commit_level_instance¶
Destructive.
Closes the in-place edit opened by edit_level_instance: the engine commits (or discards) the edits, saves the sub-level .umap back to disk, and re-collapses the streaming level into the instanced ALevelInstance. Canonical headless path: resolve the ALevelInstance by label/name, then ULevelInstanceSubsystem::CanCommitLevelInstance (gate) -> CommitLevelInstance. When the instance is NOT being edited, CanCommitLevelInstance returns false with reason "not currently being edited" — that is reported honestly as { committed:false, was_editing:false } and is a SUCCESS (a no-op close), NOT an error, so this is safe to call unconditionally to guarantee no dangling edit-mode. CommitLevelInstance returns whether the sub-level package save succeeded (committed:false on an honest save failure). Optional discard (default false) throws the edits away instead of saving. Requires the editor (GEditor); CommitLevelInstance touches GEditor->Trans / selection unguarded. Under -unattended the commit's save dialogs do not block.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Required. Label or name of the ALevelInstance actor whose edit to commit (matched via GetActorNameOrLabel). |
discard |
boolean | no | Optional, default false. When true, discard the in-place edits instead of saving them back to the sub-level .umap. |
Returns: { actor_name: string, committed: bool, was_editing: bool, discarded: bool, note: string }
configure_gravity¶
Destructive, idempotent.
Set world gravity from a named preset (Earth -980, Moon -163, Mars -371, Zero, Low, High -1960, Enabled, Disabled), writing the same WorldSettings fields as set_world_gravity and returning old/new/requested triplets plus a physics-component census of the world. Prefer set_world_gravity when you have an exact number. WARNING: gravity_configured is a real re-read (it compares GlobalGravityZ against what was asked), but an UNRECOGNISED preset name is NOT an error: it comes back gravity_configured:false with the reason in gravity_message and nothing written -- read that field, not the envelope.
| Parameter | Type | Required | Description |
|---|---|---|---|
gravity_settings |
string | yes | Preset NAME, one of 'Enabled'/'Disabled', 'Earth' (-980), 'Moon' (-163), 'Mars' (-371), 'Zero', 'Low', 'High', in any capitalisation ('EARTH' works too). For an arbitrary number use set_world_gravity. |
Returns: { gravity_settings: string, gravity_configured: bool, gravity_message: string, old_gravity_x: float, old_gravity_y: float, old_gravity_z: float, old_gravity_enabled: bool, new_gravity_x: float, new_gravity_y: float, new_gravity_z: float, new_gravity_enabled: bool, requested_gravity_x: float, requested_gravity_y: float, requested_gravity_z: float, requested_gravity_enabled: bool, world_name: string, world_physics_enabled: bool, world_physics_delta_time: float, world_physics_time_seconds: float, world_physics_real_time_seconds: float, world_physics_component_count: int, world_simulate_physics_component_count: int, world_dynamic_physics_component_count: int, gravity_impact: float, gravity_impact_rating: string, gravity_recommendations: [string] }
convert_map_to_world_partition¶
Destructive.
Reports whether the current editor world can be converted to World Partition. HONEST gate: the only complete conversion path is the UWorldPartitionConvertCommandlet (commandlet-only, needs -run=WorldPartitionConvert -AllowCommandletRendering as a separate process), and the runtime FWorldPartitionConverter::Convert mutates the level in place WITHOUT saving, so it cannot be driven safely or synchronously from this request. The tool does the headless-safe part for real (resolves the editor world, detects World Partition) and returns converted=false with a note explaining why (already WP, or commandlet-only).
| Parameter | Type | Required | Description |
|---|---|---|---|
map_path |
string | no | Optional informational path of the map to convert (the world converted is always the current editor world). |
Returns: { world: string, is_world_partition: bool, converted: bool, already_converted: bool, success: bool, note: string, message: string }
copy_landscape_region¶
Additive.
Clone a rectangle of terrain relief: copy a heightmap region between two landscapes (or within one, by omitting the source name), resampling automatically when the source and destination rectangles differ in size. Regions are in VERTEX coordinates, not world units -- get the ranges from get_landscape_info (min_x/max_x, size_x). Use it to duplicate an island or reuse sculpted relief; use import_landscape_heightmap when the source is a file instead.
| Parameter | Type | Required | Description |
|---|---|---|---|
source_region |
array | yes | Required [minX, minY, maxX, maxY] in source vertex coords |
dest_region |
array | yes | Required [minX, minY, maxX, maxY] in destination vertex coords |
landscape_actor_name |
string | no | Optional destination landscape actor name, defaults to first found |
source_landscape_actor_name |
string | no | Optional source landscape actor name, defaults to destination |
Returns: { source_landscape_actor_name: string, dest_landscape_actor_name: string, applied: bool, resampled: bool, source_width: int, source_height: int, dest_width: int, dest_height: int, source_region: [int], dest_region: [int] }
create_data_layer_asset¶
Additive.
Creates and saves a new UDataLayerAsset (World Partition data layer).
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Name of the new data layer asset. |
package_path |
string | no | Target /Game package path (optional, default "/Game/DataLayers") |
data_layer_type |
string | no | Data layer type: "Editor" or "Runtime" (optional, default "Editor") |
debug_color |
string | no | Optional [r, g, b] or [r, g, b, a] integers 0-255 (defaults to [0, 128, 255, 255]) |
Returns: { name: string, package_path: string, asset_path: string, data_layer_type: string, is_runtime: bool, debug_color: [number, number, number, number], created: bool, already_exists: bool, success: bool, saved: bool, message: string }
create_data_layer_instance¶
Additive.
Instances a UDataLayerAsset into the editor world's World Partition. Uses UDataLayerEditorSubsystem::CreateDataLayerInstance. Requires the editor world to be a World Partition world; on the default non-WP map this returns an honest "requires world partition" error (no editor-world swap is done).
| Parameter | Type | Required | Description |
|---|---|---|---|
data_layer_asset_path |
string | yes | Full /Game path to the UDataLayerAsset to instance. |
Returns: { data_layer_asset_path: string, instance_name: string, short_name: string, full_name: string, data_layer_type: string, is_runtime: bool, asset_path: string, created: bool, already_exists: bool }
create_foliage_type¶
Additive.
Create and save a FoliageType asset (UFoliageType_InstancedStaticMesh) wrapping a static mesh, so it can be placed as foliage and tuned with set_foliage_type_properties. Creating the asset is safe; note that the tools that PLACE instances of it (add_foliage_instances, scatter_foliage_in_box, scatter_foliage_on_layer) can crash the editor, so plan to scatter via instanced-static-mesh components or PCG. For landscape GRASS driven by the terrain material use create_landscape_grass_type instead.
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Asset name, e.g. FT_Grass |
static_mesh_path |
string | yes | Full path of the source StaticMesh |
package_path |
string | no | Target content path, defaults to /Game/Foliage |
Returns: { name: string, package_path: string, asset_path: string, static_mesh: string, foliage_class: string, created: bool, already_exists: bool, mesh_set: bool, saved: bool, message: string }
create_landscape¶
Additive.
Create a new terrain: spawn an ALandscape actor in the editor world sized by section_size x sections_per_component x component_count, filled with a FLAT heightmap at height. This is step 1 of two -- the relief comes from a following import_landscape_heightmap onto this actor, and going through this pair instead of the editor's New Landscape dialog is the point: the dialog treats its Location field as the terrain CENTRE (not the corner) and can fill only part of the components on import, silently. Verify the result with get_landscape_info (location, size_x/size_y, component_count), never with what you typed.
| Parameter | Type | Required | Description |
|---|---|---|---|
section_size |
string | no | Vertices per section, default 63 (rounded up to power of two) |
sections_per_component |
string | no | 1 or 2 sections per component |
component_count_x |
string | no | Components on X axis, default 8 |
component_count_y |
string | no | Components on Y axis, default 8 |
height |
string | no | Initial uint16 height value, default 32768 |
location |
array | no | Optional [x, y, z] world location |
Returns: { actor_name: string, actor_path: string, section_size: int, subsection_size_quads: int, sections_per_component: int, component_count_x: int, component_count_y: int, quads_per_component: int, size_x: int, size_y: int, vertex_count: int, height_midpoint: int, imported: bool, landscape_created: bool, location: [number] }
create_landscape_grass_type¶
Additive, idempotent.
Create and save a LandscapeGrassType asset, optionally seeding its first grass variety with a mesh. This is landscape grass, not foliage: instances are generated by the terrain MATERIAL through a LandscapeGrassOutput node, so the asset alone renders nothing until it is wired there -- and unlike the foliage scatter tools, this path does not crash the editor. Idempotent (an existing asset comes back with already_existed). Tune it with set_landscape_grass_type_properties; the honest check that the wiring resolved is ULandscapeComponent.get_grass_types_bp(), since counting grass instances headless reads 0 even when the player sees grass.
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Asset name, e.g. GT_Field |
package_path |
string | no | Target content path, defaults to /Game/Foliage |
grass_mesh |
string | no | Optional StaticMesh path; if provided, one initial FGrassVariety is added with this mesh |
Returns: { name: string, package_path: string, asset_path: string, grass_class: string, variety_count: int, created: bool, already_existed: bool, saved: bool, message: string }
create_landscape_layer_info¶
Additive, idempotent.
Create and save the LandscapeLayerInfo asset that a terrain paint layer needs before it can hold weight (grass, rock, sand, snow...). Step 1 of three: create the asset here, register it on the terrain with add_landscape_layer, then paint weight with paint_landscape_layer. Idempotent-ish -- an existing asset comes back with already_exists=true.
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Asset name, e.g. LI_Grass |
package_path |
string | no | Target content path, defaults to /Game/Landscape |
layer_name |
string | no | Engine-side weight layer name, defaults to asset name |
Returns: { name: string, package_path: string, asset_path: string, layer_name: string, layer_info_class: string, created: bool, already_exists: bool, saved: bool, message: string }
create_level_instance¶
Additive, idempotent.
Spawns an ALevelInstance actor in the editor world and binds it to a saved map (.umap). Uses the canonical headless-safe path: SpawnActor<ALevelInstance> + ALevelInstance::SetWorldAsset (NOT the editor-interactive ULevelInstanceSubsystem::CreateLevelInstanceFrom). The referenced .umap MUST already exist on disk; validated before binding so no actor is left with a broken WorldAsset. The sub-level is streamed in deferred/async, so loaded is always false here (binding != synchronous load). Idempotent: an existing ALevelInstance referencing the same world asset at the same location is returned with already_exists=true.
| Parameter | Type | Required | Description |
|---|---|---|---|
world_asset_path |
string | yes | Package/object path of the saved map to reference (e.g. "/Game/Maps/Foo"). |
location |
array | no | Optional spawn location [x, y, z] (default [0,0,0]). |
name |
string | no | Optional actor label for the spawned level instance. |
Returns: { actor_name: string, world_asset_path: string, world_asset_set: bool, world_asset_valid: bool, loaded: bool, location: [number,number,number], already_exists: bool, note: string }
create_world_partition_map¶
Additive.
Creates and saves a new World Partition-enabled UWorld map asset on disk. The editor world is NOT swapped: a new Inactive UWorld is created inside a /Game package with World Partition enabled (mirroring UWorldFactory's headless creation path) and saved as a .umap.
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | yes | Name of the new map. |
package_path |
string | no | Destination /Game folder (default /Game/Maps). |
enable_streaming |
boolean | no | bool, enable World Partition streaming (default true). |
Returns: { name: string, package_path: string, map_path: string, world_partition_enabled: bool, runtime_hash_type: string, created: bool, already_exists: bool, saved: bool, message: string, note: string }
detach_actor¶
Destructive.
Detach an actor from its current parent keeping world transform
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Name or label of the actor to detach from its parent |
Returns: { actor: string, was_attached: bool, detached: bool, former_parent: string }
edit_level_instance¶
Destructive, idempotent.
Enters in-place edit mode on an ALevelInstance: the engine unloads the instanced sub-level and re-loads it as an editable streaming level so its actors can be modified in the current editor world, then closed by commit_level_instance. Canonical headless path: resolve the ALevelInstance by label/name, then ULevelInstanceSubsystem::CanEditLevelInstance (gate) -> EditLevelInstance. CanEditLevelInstance is checked BEFORE EditLevelInstance on purpose: EditLevelInstanceInternal opens with check(CanEditLevelInstance(LI)) — a HARD ASSERT — so this ordering turns an un-editable instance into an honest error (with the engine's Reason) instead of a crash. Idempotent: an instance already in edit mode is a no-op (already_editing:true, editing:true). DEFENSIVE CRASH GUARD: on a World-Partitioned map the edit path calls FModuleManager::GetModuleChecked("LevelInstanceEditor") which asserts if that module is not loaded; when the world is partitioned AND the LevelInstanceEditor module is not loaded we fail honestly instead of proceeding. (create_level_instance produces non-partitioned maps, so the normal flow passes this guard.) Requires the editor (GEditor); EditLevelInstance touches GEditor->Trans / selection unguarded. The edit resets the undo stack and streams the world asynchronously (deferred world-swap), so the edit MUST be closed by a matching commit_level_instance.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Required. Label or name of the ALevelInstance actor to open for edit (matched via GetActorNameOrLabel). |
Returns: { actor_name: string, editing: bool, already_editing: bool, note: string }
export_landscape_heightmap¶
Destructive.
Dump the landscape heightmap (or a vertex sub-region) to a PNG or 16-bit .r16 file on disk -- THE oracle for any question about the whole terrain: whether an import really landed, where the real min/max heights are, whether a region is unfilled. Prefer it over sampling points with get_landscape_height_at when the question covers the whole surface: a handful of probes has repeatedly suggested flips and offsets that did not exist, while comparing the exported array against the source closes it in one step. An .r16 is exactly widthheight2 bytes, so a short file is itself a failure signal. Use get_landscape_height_at instead for a single world XY.
| Parameter | Type | Required | Description |
|---|---|---|---|
file_path |
string | yes | Absolute filesystem path for the exported heightmap |
landscape_actor_name |
string | no | Optional landscape actor name, defaults to first found |
region |
array | no | Optional [minX, minY, maxX, maxY] vertex region, defaults to whole landscape |
Returns: { landscape_actor_name: string, file_path: string, export_width: int, export_height: int, exported: bool, file_exists: bool, file_size: number, export_warning: string }
flatten_landscape_in_box¶
Destructive.
Level the terrain under a footprint: snap every heightmap vertex inside a world-space box to ONE absolute height, so a base, road or building pad sits flat. Give the height either as target_z in world units (converted using the landscape scale) or as a raw uint16 target_height (0..65535, where 32768 is the midpoint). Absolute, unlike set_landscape_height_in_box which adds a delta; follow with smooth_landscape_in_box to blend the hard rim it leaves. vertices_modified = 0 means the box never touched the terrain.
| Parameter | Type | Required | Description |
|---|---|---|---|
landscape_actor_name |
string | no | Optional landscape actor name, defaults to first found |
target_height |
number | no | Optional uint16 heightmap value 0 to 65535 |
target_z |
number | no | Optional target world Z, converted to uint16 using landscape scale |
box_min |
array | no | Optional [x, y, z] world-space box minimum |
box_max |
array | no | Optional [x, y, z] world-space box maximum |
center |
array | no | Optional [x, y, z] box center (alternative to box_min/box_max) |
extent |
array | no | Optional [x, y, z] box half-extents (alternative to box_min/box_max) |
Returns: { landscape_actor_name: string, target_height: int, applied: bool, vertices_modified: int, region_width: int, region_height: int, region: [int] }
focus_viewport¶
Destructive.
Frame the editor viewport on an actor or the current selection
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | no | Optional actor to focus on, defaults to current selection |
Returns: { focused_actor: string, focused_count: int }
foliage_type_exists¶
Read-only.
Yes/no guard: does this FoliageType asset path exist and load? Cheap precondition check before a create/scatter/tune call so a typo in the path fails here instead of deep inside another tool. Asks about the ASSET only -- has_foliage_instances answers whether anything of it is placed in the level.
| Parameter | Type | Required | Description |
|---|---|---|---|
foliage_type_path |
string | yes | Asset path (e.g. /Game/Foliage/BP_Tree) |
Returns: { exists: bool, asset_path: string }
get_absolute_transform¶
Read-only.
Read the absolute (world-space) location/rotation/scale flags of an EDITOR-world actor's root SceneComponent. The read-back oracle for set_absolute_transform, and the first thing to check when an attached actor inherits an unexpected offset or scale from its parent. An actor with no RootComponent answers has_root:false instead of failing.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Actor's internal name (GetName) or editor label (GetActorLabel); exact match, editor world only. |
Returns: { actor_name: string, has_root: bool, absolute_location?: bool, absolute_rotation?: bool, absolute_scale?: bool }
get_actor_blueprint¶
Read-only.
Tell whether a placed actor comes from a Blueprint and, if so, name its generated class and source asset. Cheap one-actor answer to "what BP is this thing?" -- for the reverse (all actors of a class) use get_actors_by_class. World-aware: world='editor' (default) | 'pie' | 'server' | 'client' | 'pie:N', so a RUNTIME-SPAWNED actor -- which never exists in the editor world, where it reads as a flat "Actor not found" -- can be identified too; the reply stamps world_name/world_package/net_mode/pie_instance.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Actor's internal name (GetName) or editor label (GetActorLabel); exact match. |
world |
string | no | Optional world selector: absent/'editor' (default) | 'pie' (ambiguous: PlayWorld, else the first PIE context) | 'server' (the PIE world with authority) | 'client' | 'pie:N' | 'game' (alias of 'pie'). An unrecognised value FAILS naming the worlds that exist; it never falls back to another world in silence. |
Returns: { actor_name: string, actor_class: string, world: string, is_blueprint: bool, blueprint_class?: string, blueprint_asset?: string, world_name: string|null, world_package: string|null, world_type: string|null, net_mode: string|null, pie_instance: number }
get_actor_components¶
Read-only.
List every component on one actor in the editor OR the live PIE world: name, class, is_active, plus mesh/light details. Accepts world='editor'|'pie'|'server'|'client'|'pie:N' ('server' = the PIE world with authority, 'client' = the other one) and stamps world_name/world_package/net_mode/pie_instance so a co-op reading says WHICH world it came from. Use this to discover component names; then get_component_properties (also world-aware) for their values -- reading with the default world='editor' returns the pre-BeginPlay archetype, not the running actor.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Actor's internal name (GetName) or editor label (GetActorLabel); exact match, not a substring. |
world |
string | no | Optional world selector: absent/'editor' (default) | 'pie' (ambiguous: PlayWorld, else the first PIE context) | 'server' (the PIE world with authority) | 'client' | 'pie:N' | 'game' (alias of 'pie'). |
Returns: { actor_name: string, actor_class: string, world: string, components: [{ name: string, class: string, is_active: bool, is_editable: bool, type?: string, mesh_name?: string, intensity?: number, light_color?: string }], components_count: number, world_name: string|null, world_package: string|null, world_type: string|null, net_mode: string|null, pie_instance: number }
get_actor_folder¶
Read-only.
Read an actor's outliner folder path (reader twin of set_actor_folder)
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Actor name or label in the world outliner |
Returns: { actor_name: string, folder_path: string }
get_actor_label¶
Read-only.
Read an actor's display label from the level (reader twin of set_actor_label)
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Actor name or label in the world outliner |
Returns: { actor_name: string, actor_label: string }
get_actor_lock_location¶
Read-only.
Read whether an EDITOR-world actor is location-locked in the viewport (AActor::IsLockLocation). The read-back oracle for set_actor_lock_location, and the thing to check first when a transform command reports success but the actor has not moved.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Actor's internal name (GetName) or editor label (GetActorLabel); exact match, editor world only. |
Returns: { actor_name, locked }
get_actor_references¶
Read-only.
Despite the name this does NOT find who references the actor: it lists that actor's own COMPONENTS (type/name/class), i.e. a thinner get_actor_components with no mesh/light detail. For real reference graphs use the Asset Registry tools (get_asset_referencers / get_asset_dependencies). World-aware: world='editor' (default) | 'pie' | 'server' | 'client' | 'pie:N', which also makes it see components ADDED AT RUNTIME (AddComponent in BeginPlay) that the editor world does not have; the reply stamps world_name/world_package/net_mode/pie_instance.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Actor's internal name (GetName) or editor label (GetActorLabel); exact match. |
world |
string | no | Optional world selector: absent/'editor' (default) | 'pie' (ambiguous: PlayWorld, else the first PIE context) | 'server' (the PIE world with authority) | 'client' | 'pie:N' | 'game' (alias of 'pie'). An unrecognised value FAILS naming the worlds that exist; it never falls back to another world in silence. |
Returns: { actor_name: string, actor_class: string, world: string, references: [{ type: string, name: string, class: string }], references_count: number, world_name: string|null, world_package: string|null, world_type: string|null, net_mode: string|null, pie_instance: number }
get_actors_by_class¶
Read-only.
Census of one class in a chosen world: names + locations of every actor whose class name matches EXACTLY (no subclasses; a Blueprint needs its runtime name with the _C suffix, e.g. BP_Foo_C), capped at 1000. The co-op workhorse -- world='editor'|'pie'|'server'|'client'|'pie:N' ('server' = the PIE world with authority, 'client' = the other), and the reply stamps world_name/world_package/net_mode/pie_instance so actors_count:0 is readable as "not in THIS world" instead of "does not exist". Use find_actors_by_name for substring/label search, get_actors_in_radius for proximity. Two false zeros: with 2+ PIE clients a bare world='pie' resolves to only ONE of the two worlds; and after compile_blueprint the placed OFPA instances vanish from BOTH editor and PIE worlds in memory (git shows them intact on disk -- the fix is load_level of the same map, never re-placing them).
| Parameter | Type | Required | Description |
|---|---|---|---|
class_name |
string | yes | Whole UClass name, e.g. 'StaticMeshActor' or 'BP_MyTurret_C'. Compared case-insensitively but WHOLE-string: not a path, not a substring, and never matched against parent classes. |
world |
string | no | Optional world selector: absent/'editor' (default) | 'pie' (ambiguous: PlayWorld, else the first PIE context) | 'server' (the PIE world with authority) | 'client' | 'pie:N' | 'game' (alias of 'pie'). |
Returns: { class_name: string, world: string, actors: [{ name: string, class: string, location: { x: number, y: number, z: number } }], actors_count: number, world_name: string|null, world_package: string|null, world_type: string|null, net_mode: string|null, pie_instance: number }
get_actors_in_radius¶
Read-only.
Spatial query: every actor whose ORIGIN (not its bounds) lies within radius cm of a world point, with each one's distance and location. Pick this over get_actors_by_class when the question is "what is near here" instead of "where are the X". World-aware: world='editor' (default) | 'pie' | 'server' | 'client' | 'pie:N', so actors SPAWNED AT RUNTIME -- which the editor world never contains -- are reachable, and the reply stamps world_name/world_package/net_mode/pie_instance so actors_count:0 reads as "nothing near here IN THIS WORLD" instead of "nothing near here".
| Parameter | Type | Required | Description |
|---|---|---|---|
radius |
number | yes | Search radius in centimetres (Unreal units), measured to each actor's origin. |
center |
array | no | World-space center, ARRAY form only: [x, y, z]. Omitted -- or given as an object, or with fewer than 3 numbers -- it silently becomes the origin [0,0,0], which reads exactly like "nothing is near there". |
world |
string | no | Optional world selector: absent/'editor' (default) | 'pie' (ambiguous: PlayWorld, else the first PIE context) | 'server' (the PIE world with authority) | 'client' | 'pie:N' | 'game' (alias of 'pie'). An unrecognised value FAILS naming the worlds that exist; it never falls back to another world in silence. |
Returns: { center_x: number, center_y: number, center_z: number, radius: number, world: string, actors: [{ name: string, class: string, distance: number, location: { x: number, y: number, z: number } }], actors_count: number, world_name: string|null, world_package: string|null, world_type: string|null, net_mode: string|null, pie_instance: number }
get_data_layer_asset_info¶
Read-only.
Reads type, debug color and runtime flags of a UDataLayerAsset.
| Parameter | Type | Required | Description |
|---|---|---|---|
data_layer_asset_path |
string | yes | Full /Game path to the data layer asset. |
Returns: { data_layer_asset_path: string, asset_path: string, name: string, data_layer_type: string, is_runtime: bool, is_private: bool, supports_actor_filters: bool, debug_color: [number, number, number, number] }
get_data_layer_assets¶
Read-only.
Lists the UDataLayerAsset assets (subclasses included) under a content folder and all its sub-folders, found through the Asset Registry, each with name, object path and type (Editor, Runtime or Unknown). Every match is loaded to read its type; nothing is modified and the list is not paginated. These are layer assets, not the layers of the open World Partition map: list those with get_data_layer_instances. For one asset's runtime flags and debug color use get_data_layer_asset_info.
| Parameter | Type | Required | Description |
|---|---|---|---|
path |
string | no | Content path to search (optional, default "/Game", recursive) |
Returns: { path: string, data_layer_assets: [{ name: string, path: string, type: string }], count: number }
get_data_layer_instances¶
Read-only.
Lists the editor world's data layer instances. REAL read via UDataLayerManager::ForEachDataLayerInstance. Returns an empty list on a non-WP (default) map, which is the correct result.
No parameters.
Returns: { world_name: string, is_world_partition_enabled: bool, data_layer_instances: [{instance_name, short_name, full_name, data_layer_type, is_runtime, asset_path}], count: int, note: string }
get_foliage_in_radius¶
Read-only.
List the actual foliage instances of one FoliageType inside a world-space sphere, with each one's location, rotation, scale and instance_index. Use it to check what is standing on a spot before building there, or as a dry run before remove_foliage_in_radius. Capped by max_results (default 100, hard cap 1000), so a full count must come from get_foliage_instance_count, not from len(instances).
| Parameter | Type | Required | Description |
|---|---|---|---|
foliage_type_path |
string | yes | Asset path of the UFoliageType to query |
radius |
number | yes | Radius in world units |
center_x |
number | no | X component of the world-space center of the query sphere |
center_y |
number | no | Y component of the world-space center of the query sphere |
center_z |
number | no | Z component of the world-space center of the query sphere |
max_results |
string | no | Maximum entries returned (default 100, hard cap 1000) |
Returns: { count, instances: [{location, rotation, scale, instance_index}] }
get_foliage_instance_count¶
Read-only.
Count how many instances of one FoliageType are placed across the level's InstancedFoliageActors. The cheapest oracle for "did that scatter place anything / did the removal clear it" -- one number, no transform payload. Use get_foliage_in_radius when you need WHERE they are, has_foliage_instances for a plain yes/no.
| Parameter | Type | Required | Description |
|---|---|---|---|
foliage_type_path |
string | yes | Full path of the UFoliageType asset |
Returns: { foliage_type_path: string, foliage_type: string, instance_count: int, placed_instance_count: int, foliage_actor_count: int }
get_foliage_type_properties¶
Read-only.
Read a FoliageType asset's authored tunables in one call -- density, radius, scale and z-offset ranges, cull distances, mobility, align-to-normal, random yaw, world collision, shadow and indirect-lighting flags. The read-back oracle for set_foliage_type_properties, and cheaper than reflection-walking the asset from Python. Describes the ASSET, not what is placed in the level: for that use get_foliage_instance_count / get_foliage_in_radius.
| Parameter | Type | Required | Description |
|---|---|---|---|
foliage_path |
string | yes | Asset path of the UFoliageType |
Returns: { asset_path, foliage_class, density, density_adjustment_factor, radius, scale_x:{min,max}, scale_y, scale_z, z_offset, cull_distance:{min,max}, mobility, align_to_normal, random_yaw, collision_with_world, cast_shadow, affect_dynamic_indirect_lighting }
get_foliage_types¶
Read-only.
List every FoliageType actually present in the level's InstancedFoliageActors, with the instance counts each carries. The level-side inventory ("what vegetation is in this map, and how much"), as opposed to get_foliage_type_properties which describes one asset. Nothing here means nothing has been placed, even if the FoliageType assets exist in Content.
No parameters.
Returns: { foliage_types: [object], foliage_type_count: int, foliage_actor_count: int }
get_landscape_grass_type_properties¶
Read-only.
Read one grass variety of a LandscapeGrassType asset: mesh, density, placement jitter, start/end cull distance, min LOD, scaling mode and scale ranges, rotation/alignment and shadow flags. The read-back oracle for set_landscape_grass_type_properties. Two units that mislead: grass_density is instances per TEN square metres (25 means 2.5/m2), and start_cull_distance only fades if the mesh's material uses a PerInstanceFadeAmount node -- otherwise clusters pop at end_cull_distance and the start value does nothing.
| Parameter | Type | Required | Description |
|---|---|---|---|
grass_path |
string | yes | Asset path of the ULandscapeGrassType |
variety_index |
integer | yes | Index of the FGrassVariety to read, default 0 |
Returns: { asset_path, grass_class, variety_index, variety_count, grass_mesh, grass_density, placement_jitter, start_cull_distance, end_cull_distance, min_lod, scaling, scale_x:{min,max}, scale_y, scale_z, random_rotation, align_to_surface, use_grid, cast_dynamic_shadow, receives_decals, keep_instance_buffer_cpu_copy }
get_landscape_height_at¶
Read-only.
How high is the ground here: sample the terrain surface height (world Z) at one world (x, y) -- the tool for placing an actor on the terrain, checking a spawn point is above water, or proving a region is not flat. Reads the heightmap texture directly (FHeightmapAccessor + bilinear interpolation), so unlike raycast_scene it needs NO collision, NO PIE and no cooked physics: it answers in the editor world where a line trace just misses the landscape. Honest at the edges -- outside the extent it clamps to the nearest vertex and says in_bounds=false, and it reports the (col,row) vertex it sampled so you can verify the pixel-to-world mapping. Use export_landscape_heightmap instead when the question is about the WHOLE terrain (min/max, unfilled regions, did an import land): a handful of probes has repeatedly suggested flips and offsets that were not there.
| Parameter | Type | Required | Description |
|---|---|---|---|
x |
number | no | World-space X coordinate to sample |
y |
number | no | World-space Y coordinate to sample |
landscape_actor_name |
string | no | Optional landscape actor name or label, defaults to first found |
Returns: { landscape_actor_name: string, x: number, y: number, height: number, vertex: [int, int], in_bounds: bool }
get_landscape_info¶
Read-only.
Find the terrain and read its geometry: every ALandscape actor in the editor world with its world location and scale, vertex extent (min_x/min_y/max_x/max_y, size_x/size_y) and component layout (component_count, component_size_quads, subsection_size_quads, num_subsections). The first call of any landscape task -- it gives you the actor name the other landscape tools need, and the numbers to convert a world XY into a heightmap vertex. Also the ONLY trustworthy check of where the terrain actually is: the editor's New Landscape dialog treats its Location field as the CENTRE, so a terrain can sit half a world away from the corner you typed; read location here afterwards instead of believing the input. Note it lists ALandscape actors only, not the LandscapeStreamingProxy actors a World-Partition map renders through.
No parameters.
Returns: { landscapes: [{ actor_name, actor_path, location: [x,y,z], scale: [x,y,z], component_size_quads, subsection_size_quads, num_subsections, min_x, min_y, max_x, max_y, size_x, size_y, component_count }], landscape_count: int }
get_landscape_layers¶
Read-only.
List which paint/weight layers are registered on a landscape (name plus its LandscapeLayerInfo asset). The cheap check before painting: a layer missing from this list will silently absorb any paint_landscape_layer call. Use it to discover the layer names a terrain material expects.
| Parameter | Type | Required | Description |
|---|---|---|---|
landscape_actor_name |
string | no | Optional landscape actor name, defaults to first found |
Returns: { landscape_actor_name: string, layers: [object], layer_count: int }
get_landscape_material¶
Read-only.
Read which material the terrain is currently using: the landscape's assigned render material and hole material as asset paths (direct UPROPERTY read, null when unset). The read-back oracle for set_landscape_material. It reports the ALandscape actor only -- on a World-Partition map the LandscapeStreamingProxy actors carry their own copy, so to prove the whole terrain is dressed also read landscape_material on the proxies.
| Parameter | Type | Required | Description |
|---|---|---|---|
landscape_name |
string | no | Optional landscape actor name, defaults to first found |
Returns: { landscape_name: string, material_path: string|null, hole_material_path: string|null }
get_landscape_nanite_status¶
Read-only.
Report a landscape's Nanite flags (enabled / built / up-to-date / out-of-date) without triggering a build. Read-only, editor-only. TRUST ONLY nanite_enabled: the built/up-to-date flags can CONTRADICT each other (nanite_built=false alongside nanite_up_to_date=true and out_of_date=false) and stay at built=false while the editor is visibly building the meshes -- they do not distinguish "not built" from "built and current". For "is the Nanite mesh actually built", count the "Built static mesh ...LandscapeNaniteMesh" lines in Saved/Logs/ instead.
| Parameter | Type | Required | Description |
|---|---|---|---|
landscape_actor_name |
string | no | Optional landscape actor name/label, defaults to first found |
Returns: { landscape_actor_name: string, nanite_enabled: bool, nanite_built: bool, nanite_up_to_date: bool, nanite_out_of_date: bool, note?: string }
get_landscape_spline_control_point¶
Read-only.
Read ONE landscape spline control point by index: its landscape-local location and rotation, half-width, side/end falloff, and how many segments connect to it. The per-point reader that pairs with set_landscape_spline_control_point; get_landscape_splines only gives component-level counts, so this is the only way to see where a road or river point actually sits. connected_segment_count = 0 marks a dangling point that draws nothing.
| Parameter | Type | Required | Description |
|---|---|---|---|
control_point_index |
integer | yes | Index into the splines component's ControlPoints (required) |
landscape_name |
string | no | Optional landscape actor name, defaults to first found |
Returns: { landscape_name: string, control_point_index: int, control_point_count: int, location: [number], rotation: [number], width: number, side_falloff: number, end_falloff: number, connected_segment_count: int }
get_landscape_splines¶
Read-only.
Summary of a landscape's spline component: whether it has one at all, plus the control point and segment counts. The quick "is there a road/river network on this terrain, and how big" check, and the count oracle after adding or removing points. For an individual point's position and width use get_landscape_spline_control_point -- this returns no per-point data.
| Parameter | Type | Required | Description |
|---|---|---|---|
landscape_name |
string | no | Optional landscape actor name, defaults to first found |
Returns: { landscape_name: string, has_splines_component: bool, control_point_count: int, segment_count: int }
get_level_instance_info¶
Read-only.
Lists every ALevelInstance actor in the editor world. REAL read via TActorIterator<ALevelInstance>; serialises each actor's referenced world asset and loaded state. An empty list on a map with no level instances is the correct result (honest read).
No parameters.
Returns: { world: string, level_instances: [{ actor_name: string, world_asset_path: string, world_asset_valid: bool, is_loaded: bool, location: [number,number,number] }], count: number }
get_lighting_in_area¶
Read-only.
Light-only spatial query: every actor carrying a LightComponent within radius cm of a world point, reporting light_type, intensity, color and distance. Use it to answer "why is this spot dark / blown out" without walking the whole outliner (get_actors_in_radius returns everything and no light data). World-aware: world='editor' (default) | 'pie' | 'server' | 'client' | 'pie:N', which is what lets you see lights attached to actors that only exist at runtime (a torch on a spawned character, a muzzle flash), and the reply stamps world_name/world_package/net_mode/pie_instance so lights_count:0 is readable as "not in THIS world".
| Parameter | Type | Required | Description |
|---|---|---|---|
radius |
number | yes | Search radius in centimetres (Unreal units), measured to each light actor's origin. |
center |
array | no | World-space center, ARRAY form only: [x, y, z]. Omitted -- or given as an object, or with fewer than 3 numbers -- it silently becomes the origin [0,0,0], which reads exactly like "there are no lights here". |
world |
string | no | Optional world selector: absent/'editor' (default) | 'pie' (ambiguous: PlayWorld, else the first PIE context) | 'server' (the PIE world with authority) | 'client' | 'pie:N' | 'game' (alias of 'pie'). An unrecognised value FAILS naming the worlds that exist; it never falls back to another world in silence. |
Returns: { center_x: number, center_y: number, center_z: number, radius: number, world: string, lights: [{ actor_name: string, light_type: string, intensity: number, light_color: string, distance: number, location: { x: number, y: number, z: number } }], lights_count: number, world_name: string|null, world_package: string|null, world_type: string|null, net_mode: string|null, pie_instance: number }
get_navigation_data¶
Read-only.
Inventory of navigation in a chosen world: every ANavigationData actor (the RecastNavMesh included) with its class, every NavMeshBoundsVolume with its location, and whether the world is flagged whole-world-navigable. The first thing to read when AI will not path -- no bounds volume, or a volume with an empty brush, means zero navmesh tiles. Errors honestly if the world has no navigation system at all. World-aware: world='editor' (default) | 'server' | 'client' | 'pie:N' | 'pie'. WARNING: The navmesh is SERVER-AUTHORITATIVE: asking a client answers "Navigation System not found" while the server's navmesh is perfectly alive, so anchor world='server' -- and the reply stamps world_name/world_package/net_mode/pie_instance so you can prove which one you asked.
| Parameter | Type | Required | Description |
|---|---|---|---|
world |
string | no | Optional world selector: absent/'editor' (default) | 'server' (the PIE world with authority -- the ONLY one that owns a navmesh) | 'client' | 'pie:N' | 'pie' (ambiguous) | 'game' (alias of 'pie'). An unrecognised value FAILS naming the worlds that exist; it never falls back to another world in silence. |
Returns: { world: string, navigation_data: [{ name: string, class: string }], navigation_data_count: number, nav_bounds_volumes: [{ name: string, location_x: number, location_y: number, location_z: number }], nav_bounds_volumes_count: number, navigation_system_available: bool, is_whole_world_navigable: bool, world_name: string|null, world_package: string|null, world_type: string|null, net_mode: string|null, pie_instance: number }
get_spline_points¶
Read-only.
Reads the control points of a named actor's USplineComponent (reader twin of set_spline_points). Returns each point's index and local-space location (the same space set_spline_points writes in), plus the total count and closed-loop flag.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Display label or internal name of the target editor-world actor |
Returns: { actor_name: string, component_name: string, count: int, closed_loop: bool, points: [{ index: int, location: [number, number, number] }] }
get_streaming_levels¶
Read-only.
Lists every streaming sub-level of the current editor world. Reads UWorld::GetStreamingLevels(); works even when the world has zero streaming levels (returns an empty array).
No parameters.
Returns: { streaming_levels: [{ package_name: string, name: string, streaming_class: string, should_be_loaded: bool, should_be_visible: bool, is_level_loaded: bool, is_level_visible: bool }], streaming_level_count: number, world_package: string }
get_world_partition_info¶
Read-only.
Reads the editor world's World Partition state. REAL read: works on any map. Returns is_world_partition_enabled=false on the default (non-WP) editor map, which is the correct result.
No parameters.
Returns: { world_name: string, is_world_partition_enabled: bool, num_data_layers: int, runtime_hash_type: string, is_streaming_enabled: bool, note: string }
get_world_partition_runtime_hash¶
Read-only.
Reads the editor world's World Partition runtime hash. REAL read: reports the runtime hash class and the number of GENERATED streaming grids (UWorldPartitionRuntimeSpatialHash::GetNumGrids), which is 0 until a cook/build generates the runtime grids. On the default non-WP editor map it honestly returns is_world_partition=false (no swap is done).
No parameters.
Returns: { is_world_partition: bool, runtime_hash_type?: string, num_streaming_grids?: int, success: bool, note: string }
get_world_settings¶
Read-only.
Read a world's framework wiring: default GameMode plus the pawn / PlayerController / HUD / spectator classes it hands out, and gravity, time dilation and paused state. Use this to check WHICH GameMode+PC a map will spawn; use get_world_settings_detail for the physics/KillZ/world-bounds side. World-aware: with the default world='editor' there is no live GameMode, so the classes come from the DefaultGameMode CDO -- i.e. what the map INTENDS; ask for world='server' and GetAuthGameMode() returns the GameMode a running PIE ACTUALLY instantiated, which is the read that settles a set_player_controller_class that looks applied and is not. WARNING: world_type is stamped by the canonical world evidence, so it can read 'PIE', not only Game/Editor/Other.
| Parameter | Type | Required | Description |
|---|---|---|---|
world |
string | no | Optional world selector: absent/'editor' (default) | 'pie' (ambiguous: PlayWorld, else the first PIE context) | 'server' (the PIE world with authority -- the only one with a live AuthGameMode) | 'client' | 'pie:N' | 'game' (alias of 'pie'). An unrecognised value FAILS naming the worlds that exist; it never falls back to another world in silence. |
Returns: { world: string, world_name: string, world_type: string, default_game_mode: string, default_pawn_class: string, player_controller_class: string, hud_class: string, spectator_class: string, world_gravity_enabled: bool (the effective gravity Z is non-zero), world_gravity_overridden: bool (Override World Gravity), world_gravity_z: number, time_dilation: number, paused: number, world_package: string|null, net_mode: string|null, pie_instance: number }
get_world_settings_detail¶
Read-only.
Read a world's physics/bounds side of WorldSettings: GlobalGravityZ plus the override flag AND the effective GetGravityZ, KillZ and its damage type, enable_world_bounds_checks, world_to_meters, time dilation, default GameMode and force_no_precomputed_lighting. This is the read-back for set_world_gravity / set_kill_z, and the place that tells you whether world-bounds checks are even on; use get_world_settings instead for the GameMode/pawn/PlayerController/HUD wiring. World-aware: world='editor' (default -- and it is the EDITOR world that set_world_gravity/set_kill_z actually write) | 'server' | 'client' | 'pie:N' | 'pie' read the RUNNING duplicate instead, which is how you tell "the map is authored with this gravity" apart from "the session is running with it".
| Parameter | Type | Required | Description |
|---|---|---|---|
world |
string | no | Optional world selector: absent/'editor' (default -- the world set_world_gravity and set_kill_z write, so this is their read-back) | 'server' | 'client' | 'pie:N' | 'pie' (ambiguous) | 'game' (alias of 'pie') read the live PIE duplicate. An unrecognised value FAILS naming the worlds that exist; it never falls back to another world in silence. |
Returns: { world: string, world_name: string, global_gravity_z: number, global_gravity_set: bool, effective_gravity_z: number, kill_z: number, kill_z_damage_type: string, enable_world_bounds_checks: bool, world_to_meters: number, time_dilation: number, default_game_mode: string, force_no_precomputed_lighting: bool, world_package: string|null, world_type: string|null, net_mode: string|null, pie_instance: number }
has_foliage_instances¶
Read-only.
Yes/no: does this FoliageType have any instances placed in the current level (with the count alongside)? The one-line gate for "is this vegetation actually in the map"; foliage_type_exists answers the different question of whether the asset exists at all, and get_foliage_in_radius says where the instances are.
| Parameter | Type | Required | Description |
|---|---|---|---|
foliage_type_path |
string | yes | Asset path of the UFoliageType to query |
Returns: { has_instances: bool, instance_count: int, foliage_type_path: string }
import_landscape_heightmap¶
Destructive.
Load a PNG or 16-bit .r16 heightmap file from disk and stamp it onto an existing landscape: this is the reliable route to terrain relief, and the reason to prefer it over the editor's Import from File dialog, which can fill only part of the components and drop the peak with no warning at all. It does not negotiate resolution -- create the landscape at the file's own vertex size first (create_landscape) so resampled comes back false. success/applied is an acknowledgement, not proof: the oracle is export_landscape_heightmap plus an array compare against the source file, or get_landscape_height_at probes.
| Parameter | Type | Required | Description |
|---|---|---|---|
file_path |
string | yes | Absolute filesystem path or /Game asset path of the heightmap |
landscape_actor_name |
string | no | Optional landscape actor name, defaults to first found |
flip_y |
boolean | no | Optional, flip the Y axis on import |
Returns: { landscape_actor_name: string, file_path: string, source_width: int, source_height: int, dest_width: int, dest_height: int, resampled: bool, applied: bool }
inject_analog_input¶
Destructive.
Feed an analog axis value (gamepad stick, trigger) to a running PIE session's PlayerController -- how you actually MOVE or LOOK headless, where inject_key_input only does digital keys. NOTE: A single axis sample decays to zero within a tick, so sustained motion needs hold_seconds, which re-injects every tick for that long and then neutralises with a 0.0; it is fire-and-forget and returns immediately. Requires an active PIE session and a genuinely analog key (a digital one is a clean error).
| Parameter | Type | Required | Description |
|---|---|---|---|
key |
string | yes | Required analog key name, e.g. "Gamepad_LeftX", "Gamepad_LeftTriggerAxis". Rejected with a clean error if the key is not analog. |
value |
number | yes | Required float axis value; roughly -1..1 for sticks, 0..1 for triggers. |
pie_client_index |
number | no | Optional int (default 0). Which PIE client window to target -- 0 is the server/host window in a ListenServer session, 1 the first client. |
hold_seconds |
number | no | Optional float. When > 0, the analog value is re-injected every tick for this many seconds (a single axis sample decays to zero, so sustained motion needs re-feeding), then a final 0.0 is injected to neutralize. Fire-and-forget: returns immediately and the hold runs across the next hold_seconds of PIE. Omit (or 0) for a single sample. |
Returns: { injected: bool, key: string, value: number, pie_client_index: int, hold_seconds: number }
inject_key_input¶
Destructive.
Press or release a keyboard/gamepad key at a running PIE session's PlayerController, so an agent can drive the game headless -- jump, interact, open a menu. Press and release are SEPARATE calls: a tap is two of them, a hold is press now and release later. Requires an active PIE session; use inject_analog_input for sticks and triggers (with its hold_seconds for sustained movement) and inject_mouse_button for clicks. WARNING: injected only means the event reached the controller: whether the game DID anything is a state read, and in co-op read the right world.
| Parameter | Type | Required | Description |
|---|---|---|---|
key |
string | yes | Required key name as Unreal spells it, e.g. "SpaceBar", "W", "Gamepad_FaceButton_Bottom". An unknown name is a clean error, never a silent no-op. |
event |
string | no | Optional "Pressed" (default), "Released" or "Repeat". Remember the matching Released, or the game keeps thinking the key is down. |
pie_client_index |
number | no | Optional int (default 0). Which PIE client window to target -- 0 is the server/host window in a ListenServer session, 1 the first client. |
amount_depressed |
number | no | Optional float (default 1.0). Only meaningful on the controller route. |
route |
string | no | Optional "controller" (default), "slate" or "both". NOTE: THIS IS THE DIFFERENCE BETWEEN DRIVING THE GAME AND DRIVING THE UI: the controller route goes through PlayerController::InputKey, which is the gameplay input layer -- it moves the character and fires Enhanced Input actions but NEVER moves UI focus. The slate route goes through FSlateApplication::ProcessKeyDownEvent, which is the only one that moves FOCUS, so it is the only way to test a menu's gamepad navigation headless. They are not interchangeable; "both" sends to each. |
Returns: { injected: bool, key: string, event: string, pie_client_index: int, route: string, controller_injected: bool, slate_injected: bool, slate_handled: bool, slate_note? } -- NOTE: slate_handled is Slate's own verdict on whether anything consumed the key: false usually means nothing had focus, which is the useful signal (not a failure of the call).
inject_mouse_button¶
Destructive.
Fire a simulated mouse click at a running PIE session's PlayerController: fire/aim/interact without a human at the mouse. Press and release are SEPARATE calls, so a click is two of them and a hold is press now, release later. It injects the button only -- it does not move the cursor, so aim with set_control_rotation first. Requires an active PIE session; use inject_key_input for keyboard/gamepad buttons and click_pie_widget for UMG buttons, which this does NOT reach.
| Parameter | Type | Required | Description |
|---|---|---|---|
button |
string | no | Optional "Left"|"Right"|"Middle" (default "Left"); anything else is a clean error. |
event |
string | no | Optional "Pressed" (default) or "Released". A full click needs both, in two calls. |
pie_client_index |
number | no | Optional int (default 0). Which PIE client window to aim at -- 0 is the server/host window in a ListenServer session, 1 the first client. |
Returns: { injected: bool (the event was delivered to the controller, NOT that the game reacted -- verify with state), button: string, event: string, pie_client_index: int }
is_play_in_editor_active¶
Read-only.
THE oracle for "is the game running right now": asks ULevelEditorSubsystem::IsInPlayInEditor and returns is_pie_active plus status 'Playing'/'Stopped' and the current level name. Cheap, read-only, no params. Use it to confirm start_play_in_editor / stop_play_in_editor (both answer from before the async transition finishes) and as the gate before any save -- saving with PIE up is refused by the engine. WARNING: Do NOT use the pie_active field of list_dirty_packages for this: it can report false with PIE running and answering.
No parameters.
Returns: { is_pie_active: bool, current_level: string (the EDITOR's current level, not the PIE world), status: 'Playing'|'Stopped' }
list_orphaned_ofpa_actors¶
Read-only.
Finds ExternalActors (OFPA) packages with no registered World Partition descriptor -- actors invisible to get_actors_by_class/list_world_partition_actors because their package fell out of sync with the level's registered actor set (e.g. after a bad delete+save). Three enumeration layers, most-to-least authoritative: (1) raw filesystem scan of the level's external-actors folder (catches AssetRegistry blind spots); (2) AssetRegistry GetAssetsByPath (bIncludeOnlyOnDiskAssets=true, zero-load class info via AssetClassPath); (3) IF map_path is the CURRENTLY OPEN editor world with an initialized World Partition, a live cross-check against the real descriptor set. When map_path is a DIFFERENT map (the recommended procedure: clean up orphans with the editor on another map), layer 3 is skipped and disk-and-registry-both-present candidates are reported as candidate_unconfirmed rather than a false-confident confirmed_orphan. Read-only: never loads a package, never opens/swaps to map_path.
| Parameter | Type | Required | Description |
|---|---|---|---|
map_path |
string | yes | Long package name of the level to inspect (e.g. /Game/MyGame/Maps/MainMap); does NOT need to be the open editor world (that only enables the stronger layer-3 cross-check). |
filter_generated_class |
string | no | Optional substring (case-insensitive) matched against each candidate's generated_class_name (the AssetClassPath, resolved with zero loading); also tried as a UClass IsChildOf when the string resolves to a real class. |
Returns: { map_path, external_actors_path, disk_count, asset_registry_count, live_registered_count (nullable), live_cross_check_available, confirmed_orphan_count, candidate_unconfirmed_count, candidates: [{ path, generated_class_name, is_loaded, on_disk, in_asset_registry, classification }], note }
list_world_partition_actors¶
Read-only.
Lists the editor world's World Partition actors by walking their DESCRIPTORS without loading any actor package. Unlike get_actors_by_class (which only sees LOADED AActors via TActorIterator), this reads FWorldPartitionActorDescInstance for every actor known to World Partition, INCLUDING spatially-unloaded / streamed-out ones (solving "get_actors_by_class only sees loaded actors"). Editor-world read only (WP actor descriptors are editor-only data); honest empty list on a non-WP (default) map.
| Parameter | Type | Required | Description |
|---|---|---|---|
filter_class |
string | no | Optional. Class filter: resolved to a UClass (full path, /Script name, Blueprint asset path, or bare A/U name) and matched against each descriptor's native class via IsChildOf; ALSO matched as a case-insensitive substring against the descriptor's native and base class paths (so Blueprint class names like 'BP_Foo_C' or partial names work). |
name_contains |
string | no | Optional. Case-insensitive substring matched against the actor's label, object name, and soft path. |
folder |
string | no | Optional. Case-insensitive substring matched against the actor's editor folder path. |
limit |
number | no | Optional int cap on the number of actors returned (default 2000); total_matched reports the full match count regardless of the cap. |
Returns: { world: string, is_world_partition: bool, is_initialized: bool, count: int, total_matched: int, truncated: bool, actors: [{ path: string, name: string, label: string, native_class: string, base_class: string, display_class: string, is_spatially_loaded: bool, is_loaded: bool, editor_only: bool, folder: string, runtime_grid: string, editor_bounds: {valid,origin,extent}, runtime_bounds: {valid,origin,extent}, data_layers: [string] }], note: string }
load_world_partition_region¶
Destructive.
Pins the World Partition cells intersecting an axis-aligned region [min,max] into memory for inspection (editor world). Creates a UWorldPartitionEditorLoaderAdapter backed by FLoaderAdapterShape over the box and calls ILoaderAdapter::Load(); the adapter stays REGISTERED so the region remains resident (mirrors the editor's "Load Region from Here"), which then lets get_actors_by_class / actor tools see the now-loaded actors. Honest error on a non-WP (default) map or an uninitialized World Partition. Non-destructive: it loads (pins) actors, it never spawns/edits/saves.
| Parameter | Type | Required | Description |
|---|---|---|---|
min |
array | no | [x,y,z] minimum corner of the region box in world units. |
max |
array | no | [x,y,z] maximum corner of the region box in world units. |
label |
string | no | Optional label for the loader adapter (default "MCP Load Region"). |
Returns: { world: string, is_world_partition: bool, loaded: bool, region_min: [x,y,z], region_max: [x,y,z], label: string, num_loaded_actors: int, note: string }
pack_level_actors¶
Destructive, idempotent.
Bakes a saved map (.umap) into a reusable APackedLevelActor Blueprint headless: the source level's static-mesh actors are merged into ISM components on the generated Blueprint so it streams as one cheap actor. Uses FPackedLevelActorBuilder::CreateDefaultBuilder + CreateOrUpdateBlueprint with bCheckoutAndSave=false on purpose — that builder save path is silently cancelled under -unattended (FileHelpers PR_Cancelled) and would falsely report success; instead the Blueprint package is persisted explicitly via UEditorLoadingAndSavingUtils::SavePackages and its REAL result is returned as saved. The build runs in the builder's own FPreviewScene (no editor-world swap, no PIE, no render). Requires the editor (GEditor). Idempotent: an existing Blueprint at blueprint_path is updated in place (the engine early-outs via PackedHash when the source is unchanged), never duplicated.
| Parameter | Type | Required | Description |
|---|---|---|---|
world_asset_path |
string | yes | Package/object path of the saved source map to pack (e.g. "/Game/Maps/Foo"). Must exist on disk. |
blueprint_path |
string | yes | Destination package path for the APackedLevelActor Blueprint (e.g. "/Game/Maps/BPP_Foo"). |
save |
boolean | no | Optional, default true. Persist the Blueprint package to disk and report the real save result in saved. |
Returns: { blueprint_path: string, source_world_asset: string, blueprint_created: bool, packed: bool, packed_hash: number, saved: bool, note: string }
paint_landscape_layer¶
Destructive.
Paint terrain texture layers headless: write ONE uniform weight (0-255) into a landscape weightmap over a vertex region, or the whole terrain if you omit region. Blunt by design -- it fills a rectangle, it does not brush or blend, so build variety by painting several layers over different rectangles. The layer must already be registered with add_landscape_layer or nothing is stored. Region coordinates are VERTICES, not world units: get the ranges from get_landscape_info. Check vertices_painted and paint_warning rather than the success flag.
| Parameter | Type | Required | Description |
|---|---|---|---|
layer_info_path |
string | yes | Full path of the ULandscapeLayerInfoObject asset |
landscape_actor_name |
string | no | Optional landscape actor name, defaults to first found |
weight |
string | no | 0 to 255 weight value, default 255 |
region |
array | no | Optional [minX, minY, maxX, maxY] vertex region, defaults to the whole landscape |
Returns: { landscape_actor_name: string, layer_info_path: string, layer_name: string, weight: int, painted: bool, vertices_painted: number, region: [int], paint_warning: string }
possess_pawn¶
Destructive.
Possess a pawn (by actor name/label) with the active PIE session's PlayerController (AController::Possess). Honest note (not an error) if the engine's own authority gate silently no-ops the possession (Standalone/ListenServer's local PlayerController normally has authority; a pure Client's does not).
| Parameter | Type | Required | Description |
|---|---|---|---|
pawn_actor_name |
string | yes | Required. Name or label of the pawn actor in the PIE world. |
pie_client_index |
number | no | Optional int (default 0). |
Returns: { possessed: bool, already_possessed: bool, had_authority: bool, pawn_actor_name: string, pie_client_index: int, note?: string }
remove_actor_from_data_layer_instance¶
Destructive, idempotent.
Removes an editor-world actor from a data layer instance (inverse of assign_actor_to_data_layer_instance). Uses UDataLayerEditorSubsystem::RemoveActorFromDataLayer against the data layer instance referencing the given asset. Requires a World Partition world; on a non-WP (default) map this returns an honest error (no editor-world swap). Idempotent: removed=false means the actor was not in the layer (not an error).
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Label or name of the actor in the editor world. |
data_layer_asset_path |
string | yes | Full /Game path to the UDataLayerAsset (the instance referencing it must exist in the world). |
Returns: { actor_name: string, data_layer_asset_path: string, instance_name: string, short_name: string, removed: bool, message: string }
remove_all_foliage_for_type¶
Destructive.
Delete EVERY placed instance of one FoliageType from all InstancedFoliageActors in the level -- the bulk undo for a scatter that went wrong. Destructive and not per-region; use remove_foliage_in_radius to clear only around a point. The FoliageType asset itself is untouched. Check remaining=0 in the reply, not just removed_all.
| Parameter | Type | Required | Description |
|---|---|---|---|
foliage_type_path |
string | yes | Full path of the UFoliageType asset |
Returns: { foliage_type_path: string, foliage_type: string, removed_count: int, remaining: int, foliage_actors_affected: int, removed_all: bool }
remove_data_layer_instance¶
Destructive, idempotent.
Removes a data layer instance from the editor world's World Partition (inverse of create_data_layer_instance). Uses UDataLayerEditorSubsystem::DeleteDataLayer (void), verified by read-back: after delete GetDataLayerInstance(asset) must be null. Requires a World Partition world; on a non-WP (default) map this returns an honest error (no editor-world swap). Idempotent: already_deleted=true when no instance referenced the asset before the call.
| Parameter | Type | Required | Description |
|---|---|---|---|
data_layer_asset_path |
string | yes | Full /Game path to the UDataLayerAsset whose instance should be removed from the world. |
Returns: { data_layer_asset_path: string, deleted: bool, already_deleted: bool, instance_name?: string, note?: string }
remove_foliage_in_radius¶
Destructive.
Clear foliage around a point: delete every instance of one FoliageType inside a world-space sphere -- the way to carve a building site, road or clearing out of existing vegetation without wiping the whole type. Use remove_all_foliage_for_type to remove it everywhere instead. Preview what would go with get_foliage_in_radius first; the oracle is instances_removed plus a re-count.
| Parameter | Type | Required | Description |
|---|---|---|---|
foliage_type_path |
string | yes | Asset path of the UFoliageType to remove (matches against mesh on the type) |
radius |
number | yes | Radius in world units |
center_x |
number | no | X component of the world-space center of the removal sphere |
center_y |
number | no | Y component of the world-space center of the removal sphere |
center_z |
number | no | Z component of the world-space center of the removal sphere |
Returns: { applied, instances_removed, requested_radius }
remove_landscape_layer¶
Destructive.
Unregister a target weight (paint) layer from a landscape -- the inverse of add_landscape_layer. Identify it either by layer_info_path or by layer_name. This detaches the layer from the terrain; it does not delete the LandscapeLayerInfo asset, and any material that still blends that layer will now read zero weight for it.
| Parameter | Type | Required | Description |
|---|---|---|---|
layer_info_path |
string | no | Full path of the ULandscapeLayerInfoObject asset; if omitted, resolved by layer_name via the landscape info |
layer_name |
string | no | Optional layer FName; defaults to the layer info's own GetLayerName() |
landscape_actor_name |
string | no | Optional landscape actor name, defaults to first found |
Returns: { landscape_actor_name: string, layer_info_path: string, layer_name: string, layer_removed: bool, already_absent: bool, target_layer_count: int }
remove_landscape_spline_control_point¶
Destructive.
Delete a landscape spline control point by index, and with it every segment attached to it (segments_removed says how many) -- so removing a mid-route point BREAKS the road or river in two rather than healing it; re-join the neighbours with add_landscape_spline_segment. Remaining indices shift, so delete from the highest index down when removing several.
| Parameter | Type | Required | Description |
|---|---|---|---|
control_point_index |
integer | yes | Index into the splines component's ControlPoints |
landscape_name |
string | no | Optional landscape actor name, defaults to first found |
Returns: { landscape_name: string, control_point_index: int, removed: bool, control_point_count: int, segments_removed: int, segment_count: int }
remove_landscape_spline_segment¶
Destructive.
Delete ONE landscape spline segment by index, unlinking its two endpoint control points but keeping them -- the way to cut a road or river without losing the route's points (remove_landscape_spline_control_point destroys the point and all its segments instead). Segment indices shift after a removal, so work from the highest index down.
| Parameter | Type | Required | Description |
|---|---|---|---|
segment_index |
integer | yes | Index into the splines component's Segments |
landscape_name |
string | no | Optional landscape actor name, defaults to first found |
Returns: { landscape_name: string, segment_index: int, removed: bool, segment_count: int, control_points_unlinked: int }
remove_orphaned_ofpa_actors¶
Destructive.
Honest-gated deletion of ExternalActors (OFPA) orphan packages. Every entry in actor_paths is RE-VERIFIED against a fresh 3-layer scan (never trusts the caller's list, e.g. from a stale list_orphaned_ofpa_actors call) -- only a definitive classification='confirmed_orphan' is eligible for deletion; anything else (candidate_unconfirmed / registered / registered_no_file / unknown) is refused regardless of dry_run/force_save. dry_run DEFAULTS TO TRUE (deliberate deviation from a delete-by-default signature: editor crashes around OFPA + World Partition actor deletion are documented, and this tool is unexercised) and is ALWAYS forced to true -- no override parameter exists for this -- when map_path is the CURRENTLY OPEN editor world; open a different map first to actually delete (the recommended cleanup procedure). Deletion (when dry_run=false) is raw file removal of the .uasset (+ sibling .uexp/.ubulk), NOT ObjectTools::ForceDeleteObjects on a bare AActor package -- that path is untested here for a standalone-loaded actor with no owning level, and is plausibly part of why in-editor OFPA actor deletion crashes; a package still loaded in memory is refused unless force_save=true.
| Parameter | Type | Required | Description |
|---|---|---|---|
map_path |
string | yes | Long package name of the level whose orphans to remove (e.g. /Game/MyGame/Maps/MainMap). |
actor_paths |
array | yes | Array of external-actor PACKAGE path strings to remove (the 'path' field from list_orphaned_ofpa_actors). |
dry_run |
boolean | no | Default true. When true (or forced true by the active-world gate), nothing is deleted; would_delete reports what WOULD be removed. Pass false to actually delete. |
force_save |
boolean | no | Default false. Only meaningful when dry_run=false: permits deleting a candidate that is currently loaded in memory (is_loaded=true). Never overrides the confirmed_orphan re-verification requirement or the active-world gate. |
Returns: { map_path, requested_count, refused_active_world, dry_run, would_delete: [{path, generated_class_name, is_loaded}], deleted: [{path, deleted, error?}], refused_not_orphan: [{path, classification, reason}], refused_loaded: [{path, reason}], deleted_count, note }
remove_streaming_level¶
Destructive.
Removes a streaming sub-level from the current editor world. If the sub-level is loaded, uses UEditorLevelUtils::RemoveLevelFromWorld; otherwise detaches the streaming wrapper via UWorld::RemoveStreamingLevel. The result is verified by re-querying the world's streaming levels.
| Parameter | Type | Required | Description |
|---|---|---|---|
level_package_path |
string | yes | Package path of an existing streaming sub-level. |
Returns: { package_name: string, removed: bool, method: string, streaming_level_count: number }
scatter_foliage_in_box¶
Destructive.
Scatter N seeded-random foliage instances of a type inside a world-space box (same seed = same layout). DANGER: measured CRASHING the editor process, the identical access violation as add_foliage_instances (UnrealEditor-FoliageEdit.dll) because both end in the same FFoliageInfo::AddInstance path -- lowering count does not help and the failure arrives disguised as "Connection reset". Use add_instanced_static_mesh_component + add_ism_instance to scatter instead, or PCG for rule-driven placement. Save your work before calling this at all.
| Parameter | Type | Required | Description |
|---|---|---|---|
foliage_type_path |
string | yes | Full path of the UFoliageType asset |
count |
integer | yes | Number of instances to scatter, default 8 |
seed |
string | no | Seed for the random stream, default 1337 |
center |
array | no | [x, y, z] box center in world space, default [0,0,0] |
extent |
array | no | [x, y, z] box half-extents, default [500,500,0] |
align_to_ground |
boolean | no | If true, place at the box top instead of random Z |
Returns: { foliage_type_path: string, foliage_type: string, requested: int, seed: int, align_to_ground: bool, instances_added: int, instance_count_before: int, total_instance_count: int, placed_instance_count: int, instances_added_ok: bool, center: [number], extent: [number], foliage_actor: string }
scatter_foliage_on_layer¶
Destructive.
Scatter foliage only where a landscape PAINT LAYER is strong enough: samples seeded candidates in a box, keeps those whose layer weight clears layer_weight_threshold, and rejects the rest -- so trees land on the forest layer and not on rock. The rule-driven sibling of scatter_foliage_in_box. DANGER: it reaches the same FFoliageInfo::AddInstance path that can crash the editor from its two sibling tools, so treat it as unsafe and prefer add_instanced_static_mesh_component + add_ism_instance (query the layer weight yourself) or a PCG graph. Save your work before calling it.
| Parameter | Type | Required | Description |
|---|---|---|---|
foliage_type_path |
string | yes | Asset path of the UFoliageType (e.g. /Game/Foliage/BP_Tree) |
landscape_name_or_label |
string | yes | Actor label (or name) of the target ALandscape |
layer_name |
string | yes | FName of the landscape paint layer (e.g. "Grass", "Forest") |
center |
array | no | Optional [x,y,z] world center of the scatter box (default 0,0,0) |
extent |
array | no | Optional [x,y,z] half-extent of the scatter box (default 500,500,0) |
count |
string | no | Number of candidate positions to sample (default 16) |
layer_weight_threshold |
number | no | Minimum layer weight [0,1] for placement (default 0.5) |
seed |
string | no | Random seed for deterministic scatter (default 1337) |
align_to_ground |
boolean | no | When true, candidates placed at box-top Z so ground snap is meaningful |
Returns: { applied, requested_count, instances_added, instances_rejected }
set_absolute_transform¶
Destructive, idempotent.
Make an EDITOR-world actor's root SceneComponent use ABSOLUTE (world-space) location/rotation/scale instead of inheriting from its parent -- for an attached actor that drifts or shears when its parent moves or is scaled. At least one of the three flags must be supplied (otherwise clean error), and the reply re-reads all three off the component. Read them back with get_absolute_transform; this does NOT call Modify(), so pair it with another dirtying edit or the save may skip the actor.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Actor's internal name (GetName) or editor label (GetActorLabel); exact match, editor world only. Errors if the actor has no RootComponent. |
absolute_location |
boolean | no | Optional bool. True = keep world location regardless of the parent; omitted = leave the flag untouched. |
absolute_rotation |
boolean | no | Optional bool. True = keep world rotation regardless of the parent; omitted = leave untouched. |
absolute_scale |
boolean | no | Optional bool. True = ignore parent scale (stops inherited squash/stretch); omitted = leave untouched. |
Returns: { applied: bool, actor_name: string, absolute_location: bool, absolute_rotation: bool, absolute_scale: bool (all three re-read off the root component) }
set_actor_component_collision¶
Destructive, idempotent.
Sets collision on a PLACED actor's UPrimitiveComponent (the placed-actor twin of set_blueprint_component_collision). Resolves the actor by name/label then its primitive component (by name, or the root primitive when component_name is omitted) and applies, in order: SetCollisionProfileName (expands the profile into the FBodyInstance response array), SetCollisionEnabled, then per-channel SetCollisionResponseToChannel. Channel keys accept a friendly display name ("Pawn", "Visibility", or a project CUSTOM trace/object channel) OR an ECC_* token; this is how you block a custom game channel that the BlockAll profile leaves at Ignore. After applying, collision-enabled is toggled off/on to force the FBodyInstance to rebuild its filter data, and Actor->Modify() marks the (OFPA) package dirty so save_level persists the change.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Display label or internal name of the target actor |
component_name |
string | no | Primitive component name; defaults to the actor's root primitive component when omitted |
profile |
string | no | Optional collision profile name to apply first (e.g. "BlockAll", "OverlapAllDynamic", a custom preset) |
collision_enabled |
string | no | Optional NoCollision/QueryOnly/PhysicsOnly/QueryAndPhysics |
responses |
object | no | Optional { channel: response } map; channel = friendly name or ECC_* token, response = Ignore/Overlap/Block |
world |
string | no | absent/"editor" (default; the world save_level persists) | "server" (the PIE world with authority) | "client" | "pie:N" | "pie" (ambiguous) | "game" (alias of "pie") |
Returns: { actor_name: string, component_name: string, component_class: string, profile: string, collision_enabled: string, responses_applied: [{ channel: string, response: string }], collision_enabled_effective: string, rebuilt: bool, world: string, world_name: string|null, world_package: string|null, world_type: string|null, net_mode: string|null, pie_instance: number }
set_actor_folder¶
Destructive, idempotent.
Move an editor-world actor, found by internal name or label (first match), into an outliner folder; an empty folder_path moves it back to the root. Undoable, marks the level dirty, not saved; returns the internal actor_name and folder_path as given. get_actor_folder reads it back.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Current actor name or label in the world outliner |
folder_path |
string | yes | Outliner folder path with "/" between levels, e.g. "Lighting/Sky"; an empty string moves the actor to the root. |
Returns: { actor_name: string, folder_path: string }
set_actor_label¶
Destructive, idempotent.
Set the outliner label of an editor-world actor found by internal name or current label (first match). The engine trims it and keeps the old label when the new one is invalid, for example empty, so check label in the reply. Marks the level dirty without an undo entry.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Current actor name or label in the world outliner |
new_label |
string | yes | Display label to set, e.g. "Lamp_Kitchen"; leading and trailing spaces are trimmed. |
Returns: { actor_name: string, label: string }
set_actor_lifetime¶
Destructive, idempotent.
Schedules an actor in the active world (a running PIE/game world if one exists, otherwise the editor world) for automatic destruction after N seconds via FTimerManager::SetTimer. Idempotent: re-running cancels the previous timer and resets the countdown. Used for transient effects (damage numbers, FX) that should auto-cleanup. Runtime/cooked-build safe: resolves the world via GEngine's world contexts, not GEditor, so it also works in packaged builds.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Display label or internal name of the target actor (required) |
seconds |
number | yes | Seconds until the actor is destroyed (required, >0) |
Returns: { actor_name: string, seconds: number, scheduled: bool, replaced_previous_timer: bool }
set_actor_lock_location¶
Destructive, idempotent.
Lock or unlock an actor in the EDITOR world so viewport dragging cannot move it by accident (AActor::SetLockLocation). Pin landmarks -- PlayerStart, landscape, hand-placed props -- before a batch transform pass. Calls Modify(), so it dirties the actor's package and needs a save_level to persist. Read the flag back with get_actor_lock_location. Does not affect runtime/PIE movement.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Actor's internal name (GetName) or editor label (GetActorLabel); exact match, editor world only. |
locked |
boolean | yes | True to lock, false to unlock |
Returns: { applied, actor_name, locked }
set_actor_material¶
Destructive, idempotent.
Set a component-level override material on one slot of an editor-world actor (found by name or label): on its first StaticMeshComponent, else its first other mesh component. The mesh asset and other slots are untouched. Errors when the actor, a mesh component or the material is missing. One undo step; the level is marked dirty, not saved. A slot_index outside the component's material slots is refused. For the mesh asset use set_static_mesh_material_slot; for a tweakable runtime copy, create_dynamic_material_on_actor.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Name or label of the target actor |
material_path |
string | yes | Full asset path of the UMaterialInterface |
slot_index |
number | no | Material slot index, from 0 to the component's slot count minus 1, default 0 |
Returns: { actor_name: string, material: string, slot_index: int }
set_actor_spatially_loaded¶
Destructive, idempotent.
Toggles an editor-world actor's World Partition spatial-loading flag (AActor::SetIsSpatiallyLoaded). Guarded by AActor::CanChangeIsSpatiallyLoadedFlag() because the setter check()s that precondition (same baked guard as spawn_box_volume) -- so an actor that forbids the change never crashes the editor. Wrapped in FScopedTransaction + Actor->Modify() so the flag change marks the actor's (OFPA) package dirty and survives save_level. applied=false with can_change=false is the honest result for an actor that forbids the change (e.g. a non-partitioned / always-loaded actor); nothing is mutated in that case.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Label or name of the actor in the editor world. |
is_spatially_loaded |
boolean | yes | bool desired spatial-loading flag. |
Returns: { actor_name: string, actor_path: string, requested: bool, is_spatially_loaded: bool, applied: bool, can_change: bool, changed: bool, note: string }
set_control_rotation¶
Destructive, idempotent.
Set a Controller's control rotation (AController::SetControlRotation) in the active PIE session -- aims the view and, for a possessed pawn, its control-driven facing. Targets the named pawn's controller, a named controller, or (no target_name) the PIE session's PlayerController. PIE-gated: clean error if no PIE session.
| Parameter | Type | Required | Description |
|---|---|---|---|
pitch |
number | yes | Required number. Control rotation pitch (degrees). |
yaw |
number | yes | Required number. Control rotation yaw (degrees). |
roll |
number | yes | Required number. Control rotation roll (degrees). |
target_name |
string | no | Optional. Name/label of the possessed pawn (uses its controller) or a controller; default = the PIE session's PlayerController. |
pie_client_index |
number | no | Optional int (default 0). |
Returns: { applied: bool, target: string, control_rotation: [pitch, yaw, roll], pie_client_index: int }
set_data_layer_debug_color¶
Destructive, idempotent.
Sets the debug color of a UDataLayerAsset and saves it.
| Parameter | Type | Required | Description |
|---|---|---|---|
data_layer_asset_path |
string | yes | Full /Game path to the data layer asset. |
color |
array | yes | [r, g, b] or [r, g, b, a] integers 0-255. |
Returns: { data_layer_asset_path: string, asset_path: string, debug_color: [number, number, number, number], data_layer_type: string, color_set: bool, saved: bool }
set_data_layer_initial_runtime_state¶
Destructive, idempotent.
Authors the initial runtime state ("Unloaded"|"Loaded"|"Activated") of a runtime data layer's instance in the current World Partition map, creating the instance from the asset if missing. Headless authoring (no PIE); the state takes effect when the level streams in. Requires a World Partition map (honest error otherwise).
| Parameter | Type | Required | Description |
|---|---|---|---|
data_layer_asset_path |
string | yes | Full /Game path to the (runtime) data layer asset. |
initial_runtime_state |
string | yes | "Unloaded", "Loaded" or "Activated". |
create_instance_if_missing |
boolean | no | Create the data layer instance from the asset if none exists yet (optional, default true). |
Returns: { data_layer_asset_path: string, initial_runtime_state: string, is_runtime: bool, already_existed: bool, state_set: bool, saved: bool }
set_data_layer_parent¶
Destructive, idempotent.
Sets (or clears) the parent of a data layer instance in the editor world's World Partition (twin of create_data_layer_instance). Uses UDataLayerEditorSubsystem::SetParentDataLayer, verified by read-back (GetParent() must equal the requested parent). Both instances are resolved from their UDataLayerAsset paths (create the instances first via create_data_layer_instance). Pass parent_data_layer_asset_path empty/omitted to detach (reparent to root). Requires a World Partition world; on a non-WP (default) map this returns an honest error (no editor-world swap). Idempotent: already_parented=true when the instance already had the requested parent. Note: SetParentDataLayer returns false (parented=false) when the engine rejects the relationship (CanBeChildOf()==false, e.g. a runtime child under an editor parent or a cycle); the read-back reports the honest result.
| Parameter | Type | Required | Description |
|---|---|---|---|
data_layer_asset_path |
string | yes | Full /Game path to the child UDataLayerAsset (its instance must exist in the world). |
parent_data_layer_asset_path |
string | no | Full /Game path to the parent UDataLayerAsset (its instance must exist in the world). Omit or pass empty to clear the parent (reparent to root). |
Returns: { data_layer_asset_path: string, parent_data_layer_asset_path: string, instance_name: string, parent_instance_name: string, parented: bool, already_parented: bool, note?: string }
set_data_layer_runtime_state¶
Destructive, idempotent.
Sets the LIVE runtime state ("Unloaded"|"Loaded"|"Activated") of a runtime data layer in a running World Partition game (PIE). Requires a World Partition map; outside PIE this is an honest gate (applied:false + note pointing to set_data_layer_initial_runtime_state) rather than a failure.
| Parameter | Type | Required | Description |
|---|---|---|---|
data_layer_asset_path |
string | yes | Full /Game path to the (runtime) data layer asset. |
runtime_state |
string | yes | "Unloaded", "Loaded" or "Activated". |
is_recursive |
boolean | no | Also apply to child data layers (optional, default false). |
Returns: { data_layer_asset_path: string, runtime_state: string, applied: bool, success: bool, note: string }
set_data_layer_type¶
Destructive, idempotent.
Sets the EDataLayerType ("Editor" or "Runtime") of a UDataLayerAsset and saves it. Editor-only authoring on the data asset itself (no world required); mirrors set_data_layer_debug_color.
| Parameter | Type | Required | Description |
|---|---|---|---|
data_layer_asset_path |
string | yes | Full /Game path to the data layer asset. |
data_layer_type |
string | yes | "Editor" or "Runtime". |
Returns: { data_layer_asset_path: string, asset_path: string, data_layer_type: string, is_runtime: bool, type_set: bool, saved: bool }
set_foliage_type_properties¶
Destructive, idempotent.
Set tunables of a FoliageType_InstancedStaticMesh asset in one call, only the fields you pass, then save it. Returns the read-back values with applied_count and saved; an invalid mobility fails the call. Edits the asset only: instances already placed keep their transforms. Read it with get_foliage_type_properties.
| Parameter | Type | Required | Description |
|---|---|---|---|
foliage_path |
string | yes | Asset path of a UFoliageType_InstancedStaticMesh, e.g. "/Game/Foliage/FT_Example"; actor foliage types are not found. |
density |
number | no | Instances per 1000 x 1000 uu area (10 m by 10 m) when painting. |
density_adjustment_factor |
number | no | Density multiplier used when reapplying: above 1 adds instances, below 1 removes them. |
radius |
number | no | Minimum distance in cm between foliage instances. |
scale_x |
object | no | X scale range as a JSON object {"min":0.8,"max":1.2}, either bound optional. |
scale_y |
object | no | Y scale range as a JSON object {"min":0.8,"max":1.2}, either bound optional. |
scale_z |
object | no | Z scale range as a JSON object {"min":0.8,"max":1.2}, either bound optional. |
z_offset |
object | no | Z location offset range in cm as a JSON object {"min":-5,"max":0}; either bound may be left out. |
cull_distance |
object | no | Integer interval {"min":start,"max":end} in cm: instances fade from min (only with a PerInstanceFadeAmount material node) and clusters cull beyond max; 0 disables. |
mobility |
string | no | Component mobility: Static, Stationary or Movable, case-insensitive; any other value fails the call. |
align_to_normal |
boolean | no | Tilt instances to the normal of the surface they are placed on. |
random_yaw |
boolean | no | Give each instance a random yaw around its vertical axis. |
collision_with_world |
boolean | no | Test for overlap with world geometry before placing each instance. |
cast_shadow |
boolean | no | Whether the foliage components cast shadows. |
affect_dynamic_indirect_lighting |
boolean | no | Whether the foliage injects light into dynamic indirect lighting; used only when cast_shadow is true. |
Returns: { asset_path, foliage_class, density, density_adjustment_factor, radius, scale_x:{min,max}, scale_y, scale_z, z_offset, cull_distance:{min,max}, mobility, align_to_normal, random_yaw, collision_with_world, cast_shadow, affect_dynamic_indirect_lighting, applied_count, saved, save_error? }
set_kill_z¶
Destructive, idempotent.
Set the KillZ death plane on the EDITOR world's WorldSettings: any actor falling below this world Z is destroyed, provided the world's bounds checks are enabled (read that flag with get_world_settings_detail -- with it off, KillZ does nothing and the fall looks like a bug). Optionally sets the damage type applied on the kill. Values come back RE-READ off WorldSettings, not echoed. Undoable, but it dirties the MAP: save_level to keep it.
| Parameter | Type | Required | Description |
|---|---|---|---|
kill_z |
number | yes | World-space Z height (cm) below which actors get destroyed. Put it under the lowest playable geometry, not at 0. |
kill_z_damage_type |
string | no | Optional UDamageType class name or full path (e.g. 'DamageType' or '/Script/Engine.DamageType'). Resolved BEFORE anything is written, so a bad name is a clean error and KillZ is left untouched. |
Returns: { applied_kill_z: number, kill_z: number (both re-read off WorldSettings), kill_z_damage_type: string ('None' if unset), success: bool (hardcoded) }
set_landscape_grass_type_properties¶
Destructive, idempotent.
Set fields of one grass variety of a LandscapeGrassType asset, only those you pass, and save it; an empty variety list gets one appended for index 0, and density and cull distances change only their per-platform Default value. Returns the read-back variety with applied_count and saved; read it with get_landscape_grass_type_properties.
| Parameter | Type | Required | Description |
|---|---|---|---|
grass_path |
string | yes | Asset path of the LandscapeGrassType, e.g. "/Game/Foliage/GT_Field". |
variety_index |
integer | no | Index of the FGrassVariety to edit, default 0 (appends if the array is empty) |
grass_mesh |
string | no | Path of the StaticMesh for this variety, e.g. "/Game/Foliage/SM_Grass"; an unknown path fails the call. |
grass_density |
number | no | Instances per 10 square metres (25 means 2.5 per m2), so a wrong guess is a 10x error in the instance budget. |
placement_jitter |
number | no | Jitter of the grid placement from 0 to 1; only used when use_grid is true. |
start_cull_distance |
number | no | Distance in cm where instances start to fade, an integer; it does nothing unless the grass material uses a PerInstanceFadeAmount node, and 0 disables it. |
end_cull_distance |
number | no | Distance in cm beyond which a whole grass cluster is culled, an integer. |
min_lod |
number | no | Smallest mesh LOD to render, from -1 to 8; -1 uses the MinLOD of the static mesh asset. |
scaling |
string | no | Scale mode: Uniform, Free or LockXY, case-insensitive; any other value fails the call. |
scale_x |
object | no | X scale range as a JSON object {"min":0.8,"max":1.2}, also used for every axis with Uniform scaling. |
scale_y |
object | no | Y scale range as a JSON object {"min":0.8,"max":1.2}, used only with Free scaling. |
scale_z |
object | no | Z scale range as a JSON object {"min":0.8,"max":1.2}, used with Free or LockXY scaling. |
random_rotation |
boolean | no | Give each instance a random rotation instead of a shared one. |
align_to_surface |
boolean | no | Tilt instances to the landscape normal instead of keeping them vertical. |
use_grid |
boolean | no | Place instances on a jittered grid instead of a Halton sequence. |
cast_dynamic_shadow |
boolean | no | Whether instances cast shadows with non-precomputed (dynamic) shadowing. |
receives_decals |
boolean | no | Whether the grass instances receive decals. |
keep_instance_buffer_cpu_copy |
boolean | no | Keep a CPU copy of the instance buffer, which the overlap-count queries of the grass component need. |
Returns: { asset_path, grass_class, variety_index, variety_count, grass_mesh, grass_density, placement_jitter, start_cull_distance, end_cull_distance, min_lod, scaling, scale_x:{min,max}, scale_y, scale_z, random_rotation, align_to_surface, use_grid, cast_dynamic_shadow, receives_decals, keep_instance_buffer_cpu_copy, applied_count, saved, save_error? }
set_landscape_height_in_box¶
Destructive, idempotent.
Raise or lower terrain: add delta_z world units to every heightmap vertex inside a world-space box (give box_min/box_max, or center/extent). A RELATIVE edit -- to force a region to one absolute height use flatten_landscape_in_box, and to soften the seams afterwards use smooth_landscape_in_box. Check vertices_modified in the reply: a zero means the box missed the terrain, which is what a wrongly-signed world coordinate looks like.
| Parameter | Type | Required | Description |
|---|---|---|---|
landscape_actor_name |
string | no | Optional landscape actor name, defaults to first found |
delta_z |
number | no | World Z delta to apply to every vertex in the region |
box_min |
array | no | Optional [x, y, z] world-space box minimum |
box_max |
array | no | Optional [x, y, z] world-space box maximum |
center |
array | no | Optional [x, y, z] box center (alternative to box_min/box_max) |
extent |
array | no | Optional [x, y, z] box half-extents (alternative to box_min/box_max) |
Returns: { landscape_actor_name: string, delta_z: number, delta_steps: int, applied: bool, vertices_modified: int, region_width: int, region_height: int, region: [int] }
set_landscape_material¶
Destructive, idempotent.
Dress the terrain: assign the landscape's render material (and optionally its hole material) by asset path. Does MORE than the name suggests and that is the point -- it PROPAGATES to every LandscapeStreamingProxy, which is what actually renders on a World-Partition map, so you do not have to walk the proxies by hand. Consequence to budget for: it dirties one package per proxy plus the landscape. Idempotent (re-assigning the same material returns already_set), and the shader recompile is async even though the assignment is immediate. Do not trust material_assigned as the oracle -- re-read with get_landscape_material and spot-check a proxy's own landscape_material.
| Parameter | Type | Required | Description |
|---|---|---|---|
material_path |
string | yes | Asset path of the UMaterialInterface (e.g. "/Engine/EngineMaterials/WorldGridMaterial") |
landscape_name |
string | no | Optional landscape actor name, defaults to first found |
hole_material_path |
string | no | Optional asset path of the UMaterialInterface used for components with holes |
Returns: { landscape_name: string, material_path: string, material_assigned: bool, already_set: bool, hole_material_path?: string, hole_material_assigned?: bool, note: string }
set_landscape_spline_control_point¶
Destructive, idempotent.
Move, rotate or re-width one existing landscape spline control point by index -- how you adjust a road or river route without rebuilding the spline. Only the fields you pass change (applied_count reports how many landed). Location is LANDSCAPE-LOCAL, not world, and width is a HALF-width. Read the current values first with get_landscape_spline_control_point.
| Parameter | Type | Required | Description |
|---|---|---|---|
control_point_index |
integer | yes | Index into the splines component's ControlPoints |
landscape_name |
string | no | Optional landscape actor name, defaults to first found |
location |
array | no | Optional [x, y, z] in landscape-local space; only applied if provided |
rotation |
array | no | Optional [pitch, yaw, roll]; only applied if provided |
width |
number | no | Optional half-width at this point; only applied if provided |
Returns: { landscape_name: string, control_point_index: int, control_point_count: int, applied_count: int, location: [number], rotation: [number], width: number, updated: bool }
set_pie_window_size¶
Destructive, idempotent.
Set the size of the Play-In-Editor window, so a UI can be checked at more than whatever resolution the window happens to have. start_play_in_editor takes no size parameter, so without this the classic UI bug -- fine at 1920x1080, overlapping at 1280x720 -- cannot be reproduced headless. Writes ULevelEditorPlaySettings, the same setting the editor's Play dropdown edits, and it applies to the NEXT PIE session: one already running keeps its window. For a single Widget Blueprint you do not need PIE at all -- render_widget_preview takes width/height/scale directly.
| Parameter | Type | Required | Description |
|---|---|---|---|
width |
number | yes | Window width in pixels (clamped to 160..7680). |
height |
number | yes | Window height in pixels (clamped to 120..4320). |
center |
boolean | no | Center the new window on screen (default true). |
Returns: { width: int, height: int, center: bool, applies_to: string, pie_currently_active: bool } -- applies_to is always "next PIE session"; WARNING: pie_currently_active:true is the warning that what is on screen RIGHT NOW is not what you just set.
set_player_controller_class¶
Destructive, idempotent.
Point the world's GameMode at a PlayerController class, writing the live GameMode instance if one exists and otherwise the defaults of the world's Blueprint GameMode (refused when the GameMode is a native class, or when the world has none: those defaults are process-wide and never saved). success is read back from the slot written. WARNING: It does NOT compile or save the GameMode Blueprint, so a later PIE can still instantiate the OLD class from the already-compiled BlueprintGeneratedClass (three reads can agree on the new class while PIE spawns the engine default). Always follow with compile_blueprint on the GameMode and then save_asset, and verify in PIE by the SPAWNED controller's full class path -- never by re-reading this slot.
| Parameter | Type | Required | Description |
|---|---|---|---|
player_controller_class |
string | yes | Class name or full path (e.g. '/Game/MyGame/Core/BP_MyPlayerController.BP_MyPlayerController_C'); rejected if it is not a child of APlayerController. |
Returns: { player_controller_class: string, game_mode_class: string, written_to: string ('live_game_mode' | 'game_mode_defaults'), success: bool (the written slot reads back the class; still not a PIE oracle) }
set_preserve_scale_ratio¶
Destructive, idempotent.
DOES NOTHING and says so: the editor's preserve-scale-ratio preference (UEditorPerProjectUserSettings::bPreserveScaleRatio) is not in the public UPROPERTY set, so this tool writes nothing and always answers applied:false with a note pointing at Editor Preferences > Level Editor > Viewports. Kept only so the call fails loudly instead of silently; it does not affect set_actor_transform, whose scale is always taken literally.
| Parameter | Type | Required | Description |
|---|---|---|---|
preserve |
boolean | yes | Required bool, accepted and echoed back but never applied to anything. |
Returns: { applied: false (always), preserve: bool (your input, echoed), note: string explaining the gap }
set_spline_points¶
Destructive, idempotent.
Replaces the spline points on a named actor's USplineComponent. ClearSplinePoints + AddSplinePoint each (local space) + optional SetClosedLoop + UpdateSpline.
| Parameter | Type | Required | Description |
|---|---|---|---|
actor_name |
string | yes | Display label or internal name of the target editor-world actor |
points |
array | yes | [[x, y, z], ...] spline points in local space |
closed_loop |
boolean | no | Optional bool; toggles closed-loop mode |
Returns: { actor_name: string, component_name: string, num_points: int, closed_loop: bool, points_set: bool }
set_streaming_level_loaded¶
Destructive, idempotent.
Sets whether a streaming sub-level should be loaded (ULevelStreaming::SetShouldBeLoaded).
| Parameter | Type | Required | Description |
|---|---|---|---|
level_package_path |
string | yes | Package path of an existing streaming sub-level. |
loaded |
boolean | yes | Desired should-be-loaded state. |
Returns: { package_name: string, name: string, streaming_class: string, should_be_loaded: bool, should_be_visible: bool, is_level_loaded: bool, is_level_visible: bool, requested_loaded: bool, applied: bool }
set_streaming_level_visible¶
Destructive, idempotent.
Set the game-time should-be-visible request flag (ULevelStreaming bShouldBeVisible) of a streaming sub-level of the editor world, found by package path or short name, inside an undo transaction. It is a request, not an immediate change, and the editor viewport follows the level's separate editor-visibility flag, so is_level_visible may not change. Marks the map dirty without saving; an unknown level is an error. applied compares the flag with visible. Loading: set_streaming_level_loaded; current state: get_streaming_levels; adding a sub-level: add_streaming_level.
| Parameter | Type | Required | Description |
|---|---|---|---|
level_package_path |
string | yes | Package path of an existing streaming sub-level. |
visible |
boolean | yes | Desired should-be-visible state. |
Returns: { package_name: string, name: string, streaming_class: string, should_be_loaded: bool, should_be_visible: bool, is_level_loaded: bool, is_level_visible: bool, requested_visible: bool, applied: bool }
set_view_target¶
Destructive, idempotent.
Point the active PIE session's PlayerController camera at an actor (APlayerController::SetViewTargetWithBlend). blend_time=0 cuts instantly; >0 blends linearly. PIE-gated: clean error if no PIE session. Frames captures without spawning a camera by hand.
| Parameter | Type | Required | Description |
|---|---|---|---|
target_actor_name |
string | yes | Required. Name/label of the actor to view through (its camera/eyes) in the PIE world. |
blend_time |
number | no | Optional number (default 0). Seconds to blend from the current view target. |
pie_client_index |
number | no | Optional int (default 0). |
Returns: { applied: bool, view_target: string, blend_time: float, pie_client_index: int, note?: string }
set_world_gravity¶
Destructive, idempotent.
Set an exact global gravity on the EDITOR world's WorldSettings: writes GlobalGravityZ and the "Override World Gravity" flag, then RE-READS GetGravityZ() into the reply so gravity_z is a measurement rather than an echo. Earth is about -980 with the default centimetre unit. Use this when you want a number; use configure_gravity for named presets (Earth/Moon/Mars/Zero). Undoable (wrapped in a transaction) but it dirties the MAP -- save_level to keep it, and check the .umap is not read-only or the save writes nothing.
| Parameter | Type | Required | Description |
|---|---|---|---|
gravity_z |
number | yes | Custom gravity along Z in cm/s^2 (negative = downward; Earth is about -980). |
enable_override |
boolean | no | Optional bool (default true). True makes the world use gravity_z; false disables the override so the project default applies again. |
Returns: { applied_gravity_z: number (what landed in GlobalGravityZ), enable_override: bool, gravity_z: number (re-read GetGravityZ, the effective value), success: bool (hardcoded) }
set_world_partition_runtime_hash¶
Destructive, idempotent.
HONEST gate for editing the World Partition runtime hash grid settings. Mirrors HandleBuildMinimap: the WP runtime grid settings (CellSize/LoadingRange) live in UWorldPartitionRuntimeSpatialHash::Grids, an editor-only private UPROPERTY with NO public setter, and the streaming grid is generated during cook/build (GenerateStreaming is WITH_EDITOR), so it cannot be set synchronously headless. The tool resolves the editor world + detects WP for real and reports applied=false; nothing is mutated. On the non-WP default map it honestly returns is_world_partition=false.
| Parameter | Type | Required | Description |
|---|---|---|---|
cell_size |
number | no | Informative only (accepted, not applied): desired streaming cell size. |
loading_range |
number | no | Informative only (accepted, not applied): desired loading range. |
grid_name |
string | no | Informative only (accepted, not applied): target grid name. |
Returns: { is_world_partition: bool, runtime_hash_type?: string, applied: bool, runtime_regenerated?: bool, success: bool, note: string }
smooth_landscape_in_box¶
Destructive.
Soften terrain: run a 3x3 box blur over the heightmap inside a world-space box, 1 to 5 iterations. The finisher for the other two sculpt tools -- flatten_landscape_in_box and set_landscape_height_in_box leave a hard rim, and a couple of iterations here blends it. It only averages what is there; it cannot add relief.
| Parameter | Type | Required | Description |
|---|---|---|---|
landscape_actor_name |
string | no | Optional landscape actor name, defaults to first found |
iterations |
number | no | Number of smoothing iterations 1 to 5 |
box_min |
array | no | Optional [x, y, z] world-space box minimum |
box_max |
array | no | Optional [x, y, z] world-space box maximum |
center |
array | no | Optional [x, y, z] box center (alternative to box_min/box_max) |
extent |
array | no | Optional [x, y, z] box half-extents (alternative to box_min/box_max) |
Returns: { landscape_actor_name: string, iterations: int, applied: bool, vertices_smoothed: int, region_width: int, region_height: int, region: [int] }
spawn_level_streaming_volume¶
Additive, idempotent.
Spawns an ALevelStreamingVolume with a box brush and binds it to an existing streaming sub-level. Builds a default box brush (CubeBuilder via UActorFactory::CreateBrushForVolumeActor), applies the usage/previs/disabled flags, then appends the volume to the target ULevelStreaming::EditorStreamingVolumes array (idempotent: re-binding the same volume is a no-op). The actual load/unload trigger is runtime/PIE-only and is not exercised headless.
| Parameter | Type | Required | Description |
|---|---|---|---|
streaming_level_name |
string | yes | Package path (or short name) of an existing streaming sub-level to bind the volume to. |
location |
array | no | [x, y, z] world location for the volume (default [0,0,0]). |
extent |
array | no | Optional [x, y, z] box half-extent (default [100,100,100]); each axis is clamped > 0. |
usage |
string | no | Optional EStreamingVolumeUsage: one of Loading, LoadingAndVisibility (default), VisibilityBlockingOnLoad, BlockingOnLoad, LoadingNotVisible. |
editor_pre_vis_only |
boolean | no | Optional bEditorPreVisOnly flag (default false). |
disabled |
boolean | no | Optional bDisabled flag (default false). |
actor_label |
string | no | Optional editor label for the spawned volume. |
Returns: { actor_name, actor_label, actor_class, brush_built, streaming_level, usage, bound, already_bound, streaming_level_names: [string], success, note }
spawn_navmesh_bounds_volume¶
Additive.
Spawns a navigation mesh bounds volume at a specified location with optional extent, and builds a REAL cube brush so the volume has non-empty nav bounds (an empty brush yields 0 navmesh tiles). No hand placement in the editor UI required. The brush is RE-READ off the spawned actor after building (poly count from its UModel, bounds from the actor), so nothing in the payload is a hand-written claim.
| Parameter | Type | Required | Description |
|---|---|---|---|
location |
array | no | Optional [X, Y, Z] world location (defaults to origin) |
extent |
array | no | Optional [X, Y, Z] SEMI-EXTENT (half-extent) in cm (defaults to [1000, 1000, 500]). The built cube's FULL edge length is 2x this on every axis -- e.g. extent [1000, 1000, 500] yields a 2000 x 2000 x 1000 cube. Echoed back under requested.extent; what the actor ended up with is bounds_extent_actual. |
Returns: { actor_name: string, actor_path: string, location_x: number, location_y: number, location_z: number, extent_x: number, extent_y: number, extent_z: number, brush_built: bool, has_brush_geometry: bool, brush_present: bool, brush_poly_count: number (-1 = no UModel/no editor-only Polys data), brush_empty: bool, bounds_valid: bool, bounds_extent_x: number, bounds_extent_y: number, bounds_extent_z: number, bounds_extent_actual: { x, y, z }, bounds_origin_actual: { x, y, z }, actor_scale: { x, y, z }, location_actual: { x, y, z }, requested: { extent }, success: bool }
spawn_text_render_actor¶
Additive.
Spawns a TextRenderActor into the active world (a running PIE/game world if one exists, otherwise the editor world) and configures its text. Sets the UTextRenderComponent's text / color / world size if given (world_size read back to verify). Runtime/cooked-build safe: resolves the world via GEngine's world contexts, not GEditor, so it also works in packaged builds.
| Parameter | Type | Required | Description |
|---|---|---|---|
text |
string | no | Optional text to assign to the text render component |
location |
array | no | Optional [x, y, z] world location |
rotation |
array | no | Optional [pitch, yaw, roll] world rotation |
color |
array | no | Optional [r, g, b] 0..255 color (alpha forced opaque) |
size |
number | no | Optional world size for the text render component |
Returns: { actor_name: string, actor_internal_name: string, actor_class: string, has_component: bool, text_set: bool, color_set: bool, size_set: bool, world_size: number, spawned: bool }
start_play_in_editor¶
Destructive.
Press Play: starts a real PlayInEditor session (a true play world with a spawned PlayerController, not SimulateInEditor), optionally multi-client and networked for co-op testing via number_of_clients + net_mode=ListenServer. WARNING: RequestPlaySession is ASYNC and this tool probes right after asking, so pie_started comes back FALSE on a start that is perfectly fine -- the oracle is a follow-up is_play_in_editor_active, never this field. With 2+ clients the worlds are UEDPIE_0 (server) and UEDPIE_1 (client), and later reads must be anchored with world='server'/'client' because PIE actor NAMES are swapped between them. Refuses if another MCP session (or a human) already owns PIE unless force=true.
| Parameter | Type | Required | Description |
|---|---|---|---|
number_of_clients |
number | no | Optional int (default 1, clamped 1-10). >1 opens additional client windows -- that is what makes a co-op reading possible at all. |
net_mode |
string | no | Optional string: "Standalone"|"ListenServer"|"Client" (default "Standalone"). Any other value is a clean error, not a silent fallback. Use ListenServer for co-op. |
run_under_one_process |
boolean | no | Optional bool (default true). Must stay true for multi-client windows to open inside this single editor process. |
force |
boolean | no | Optional bool (default false). Override the PIE-ownership guard: start even if another session (or a manually-started PIE) currently owns Play-in-Editor. Read by the server before the tool runs, so a non-owner session can seize PIE. |
Returns: { pie_started: bool (probed synchronously right after an ASYNC request -- usually false even on success; confirm with is_play_in_editor_active), already_in_pie: bool, message: string, number_of_clients: int, net_mode: string, dirty_package_count: int, readonly_dirty_count: int, dirty_packages: [string] (capped at 25), dirty_packages_truncated: bool }
stop_play_in_editor¶
Destructive.
Press Stop: requests the end of the Play-in-Editor session (EditorRequestEndPlay). WARNING: pie_stopped is HARDCODED true whenever PIE was running and teardown is async, so the only oracle is a follow-up is_play_in_editor_active. WARNING: Treat every call as an operation that CAN KILL THE EDITOR: any UWorld/UPackage handle left in an execute_python global keeps the PIE world rooted and the engine aborts with "Object ... from PIE level still referenced" -- purge the main namespace and gc.collect() BEFORE calling. Refuses when another MCP session (or a human) started the PIE, and then needs force=true.
| Parameter | Type | Required | Description |
|---|---|---|---|
force |
boolean | no | Optional bool (default false). Override the PIE-ownership guard: stop even if another session (or a manually-started PIE) currently owns Play-in-Editor. Read by the server before the tool runs; without it, stopping a PIE your session does not own is refused with pie_owner/requester in the payload. |
Returns: { pie_stopped: bool (hardcoded true when PIE was up -- not a measurement), was_in_pie: bool, still_in_pie: bool (read immediately, so usually still true: teardown is async), message: string }
wait_for_pie_completion¶
Read-only.
Block until the human closes Play-in-Editor (or the timeout fires), pumping the game thread while it polls, and report elapsed_seconds + whether it completed or timed out. Use it to hand the session to a human for a piloted run and get control back when they hit Stop; use is_play_in_editor_active for an instant, non-blocking check. Returns immediately with started_in_pie:false when PIE was not running.
| Parameter | Type | Required | Description |
|---|---|---|---|
timeout_seconds |
number | no | Optional float (default 30). Upper bound on the wait; 0 or less means wait indefinitely. |
poll_interval_seconds |
number | no | Optional float (default 0.1). Seconds between IsInPlayInEditor probes; anything below 0.01 is floored to 0.01. |
Returns: { started_in_pie, still_active, timed_out, elapsed_seconds, completed }