Python Module Example

The Actor code examples as one big module-style example

import unreal

EditorActorSubsystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)
LevelEditorSubsystem = unreal.get_editor_subsystem(unreal.LevelEditorSubsystem)
UnrealEditorSubsystem = unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem)


def get_asset_from_actor(actor):
    """
    Get the content browser asset path of the given actor,
    support must be added for each asset type
    """
    asset = None

    # the source asset is usually stored on the root component
    # and is generally unique per component class type,
    # support will need to be added for each Actor class (joy)
    if isinstance(actor.get_class(), unreal.BlueprintGeneratedClass):
        asset = unreal.load_asset(actor.get_class().get_outer().get_path_name())
    elif isinstance(actor, unreal.StaticMeshActor):
        asset = actor.static_mesh_component
    elif isinstance(actor, unreal.SkeletalMeshActor):
        asset = actor.skeletal_mesh_component.skeletal_mesh_asset
    elif isinstance(actor, unreal.NiagaraActor):
        asset = actor.niagara_component.get_asset()
    elif isinstance(actor, unreal.LevelInstance):
        asset = actor.get_world_asset().get_outer().get_path_name()
    else:
        unreal.log_warning(
            f"\n\tActor {actor.get_actor_label()} has an unknown "
            f" or unsupported source asset ({actor.get_class()})"
            f"\n\t\tEither the actor does not have a source asset"
            f" in the Content Browser"
            f"\n\t\tor get_asset_from_actor() does not yet support"
            f" its class type"
        )

    return asset 



def get_all_actors(include_possessables = True, include_spawnables = True):
    """
    Get the list of Actors in the current Editor World / 3D Level
    """
    actors = []
    if include_possessables:
        actors += EditorActorSubsystem.get_all_level_actors() or []
    if include_spawnables:
        actors += unreal.GameplayStatics.get_all_actors_with_tag(
            UnrealEditorSubsystem.get_editor_world(),
            "SequencerActor"
        ) or []
    return actors


def get_root_actors():
    """Get all root actors (top-most in the 3D Level)"""
    return [
        actor
        for actor in get_all_actors()
        if not actor.get_attach_parent_actor() 
        and not actor.get_parent_actor()
    ]


def walk_component(component, owner=None, indent=2):
    """walk the given component to print its hierarchy"""
    if not component:
        return
    
    # validate the component's owner
    if not owner:
        owner = component.get_owner()
    if component.get_owner() != owner:
        return
    
    print(f"{'  '*indent}{component.get_name()}  (component)")

    # recurse through any immediate children
    for child in component.get_children_components(False):
        walk_component(child, owner , indent+2)


def walk_actor(actor, indent=0):
    """walk the given actor to print its hierarchy"""
    print(f"{'  ' * indent}{actor.get_actor_label()}")

    # separate the nested actors from the spawned actors:
    spawned_actors = actor.get_all_child_actors()
    nested_actors = [
        child 
        for child in actor.get_attached_actors()
        if child not in spawned_actors          
    ]
    walk_component(actor.root_component, indent=indent+2)
    
    # print the spawned actors
    for child in spawned_actors:
        print(f"{'  ' * (indent+2)}{child.get_actor_label()}  (spawned)")
    
    # walk the nested actors
    for child in nested_actors:
        walk_actor(child, indent+2)


def selection_tracker(selection_set: unreal.TypedElementSelectionSet):
    if selection_set.get_num_selected_elements():
        print(f"The following objects are currently selected:")
        for selected in selection_set.get_selected_objects():
             print(f"\t{selected.get_path_name()}")
    else:
        print("no objects selected!")


# Demo Code to Run

# Walk actors
for actor in get_root_actors():
    walk_actor(actor)

# Print Source assets if available
for actor in get_all_actors():
    print(f"{actor.get_actor_label()} source asset: {get_asset_from_actor(actor)}")

# Selection Changed callback
selection_set = LevelEditorSubsystem.get_selection_set()
selection_set.on_selection_change.add_callable(selection_tracker)

Last updated