Wrong skill for MetaSound assets? If the user asked about MetaSound, MS_ assets, or UMetaSoundSource, unload this skill and load the metasounds skill instead:
manage_skills(action="load", skill_name="metasounds")
SoundCue and MetaSound are completely separate systems — do not use SoundCueService for MetaSound tasks.
connect_nodes(parent, child, slot) means: child provides audio INTO parent at that input slot.
set_root_node(index) makes that node the final output (what you hear).
Critical Rules
⚠️ Bool Properties — b prefix stripped in Python
UE strips the b prefix from bool UPROPERTY names in Python:
C++ / UPROPERTY
Python attribute
bSuccess
success
bIsRootNode
is_root_node
bLooping
is_looping
bStreaming
is_streaming
⚠️ Node indices are positional and may shift
list_nodes() returns nodes in graph order — indices can change if new nodes are added.
Always call list_nodes() to get current indices before connecting or modifying nodes.
⚠️ connect_nodes parameter order
# parent receives audio FROM child at slot
svc.connect_nodes(cue_path, parent_index, child_index, input_slot)
# CORRECT: WavePlayer(0) feeds into Random(1) at slot 0
svc.connect_nodes('/Game/MyCue', 1, 0, 0)
# WRONG: don't confuse child/parent order
Workflows
Create a Simple SoundCue
import unreal
svc = unreal.SoundCueService()
# Create the asset (optionally wire an initial WavePlayer)
r = svc.create_sound_cue('/Game/Audio/SC_Footstep', '')
assert r.success, r.message
# Add a WavePlayer node
r = svc.add_wave_player_node('/Game/Audio/SC_Footstep', '/Game/Audio/Footstep_01', -250, 0)
assert r.success
# Set it as the root (output)
nodes = svc.list_nodes('/Game/Audio/SC_Footstep')
svc.set_root_node('/Game/Audio/SC_Footstep', nodes[0].node_index)
# Save
svc.save_sound_cue('/Game/Audio/SC_Footstep')
Random from Multiple Waves
import unreal
svc = unreal.SoundCueService()
cue = '/Game/Audio/SC_Footsteps'
svc.create_sound_cue(cue, '')
# Add 3 wave players
for i, wave in enumerate(['/Game/Audio/Step_01', '/Game/Audio/Step_02', '/Game/Audio/Step_03']):
svc.add_wave_player_node(cue, wave, -400, i * 150)
# Add a Random node to select one
svc.add_random_node(cue, -150, 150)
nodes = svc.list_nodes(cue)
# nodes[0..2] = WavePlayers, nodes[3] = Random
random_idx = next(i for i, n in enumerate(nodes) if 'Random' in n.node_class)
for i in range(3):
svc.connect_nodes(cue, random_idx, i, i) # each wave into random
svc.set_root_node(cue, random_idx)
svc.save_sound_cue(cue)
Mixer (parallel blend)
import unreal
svc = unreal.SoundCueService()
cue = '/Game/Audio/SC_Ambient'
svc.create_sound_cue(cue, '')
svc.add_wave_player_node(cue, '/Game/Audio/Wind', -400, 0)
svc.add_wave_player_node(cue, '/Game/Audio/Rain', -400, 150)
svc.add_mixer_node(cue, 2, -150, 75) # 2 inputs
nodes = svc.list_nodes(cue)
wave0 = next(i for i, n in enumerate(nodes) if 'WavePlayer' in n.node_class and i == 0)
wave1 = next(i for i, n in enumerate(nodes) if 'WavePlayer' in n.node_class and i != wave0)
mixer = next(i for i, n in enumerate(nodes) if 'Mixer' in n.node_class)
svc.connect_nodes(cue, mixer, wave0, 0)
svc.connect_nodes(cue, mixer, wave1, 1)
svc.set_root_node(cue, mixer)
svc.save_sound_cue(cue)
Routes by bool parameter; True(0) False(1) Unset(2)
optional param name last
add_param_cross_fade_node(path, num_inputs, x, y)
Crossfades by named float param
num_inputs 2–32
add_quality_level_node(path, x, y)
One input per quality level
—
Node Management
Method
Returns
Notes
list_nodes(path)
TArray<FSoundCueNodeInfo>
index, class, children, is_root_node
connect_nodes(path, parent, child, slot)
bool
child feeds audio INTO parent
disconnect_node(path, parent_index, slot)
bool
break a single input link
set_root_node(path, index)
bool
sets cue output node
set_wave_player_asset(path, index, wave_path)
bool
reassign wave on existing node
remove_node(path, index)
bool
delete a node from the graph
move_node(path, index, x, y)
bool
reposition a node in the graph
get_node_property(path, index, prop_name)
FString
read any node UPROPERTY
set_node_property(path, index, prop_name, value)
bool
write any node UPROPERTY
Cue-Level Settings
Method
Returns
Notes
set_volume_multiplier(path, vol)
bool
—
set_pitch_multiplier(path, pitch)
bool
—
set_sound_class(path, class_path)
bool
—
set_attenuation(path, att_path)
bool
att_path='' to clear
get_attenuation(path)
FString
returns asset path or ''
set_concurrency(path, conc_path, clear=False)
bool
conc_path='' + clear=True to clear all
get_concurrency(path)
TArray<FString>
list of assigned concurrency asset paths
FSoundCueNodeInfo fields
n.node_index # int — position in list_nodes array
n.node_class # str — e.g. "SoundNodeWavePlayer"
n.node_title # str — display name
n.pos_x, n.pos_y # float — graph position
n.is_root_node # bool — True if this node is SoundCue.FirstNode
n.child_indices # list[int] — indices of connected children (-1 = unconnected slot)