Published on

Unreal Engine의 Actor Palette 사용성 개선하기

Authors
  • avatar
    Name
    Beni
    Twitter
    Tech Lead

Actor Palette + 자동 배치 플러그인 제작기

안녕하세요, 리얼드로우의 테크리드 Beni입니다.

언리얼 엔진은 아티스트와 레벨 디자이너가 오브젝트를 보다 빠르게 배치할 수 있도록 다양한 에디터 기능을 제공합니다. 그 중 하나가 Actor Palette라는 기능 입니다. Actor Palette는 특정 레벨에서 자주 쓰는 액터를 “팔레트”처럼 모아두고 드래그 앤 드롭으로 바로 배치할 수 있는 기능인데, 잘 만들어진 프로젝트에서는 생산성을 크게 끌어올리는 요소가 됩니다.

하지만 실제 프로덕션에서는 이런 문제가 생기곤 합니다.

  • 동일한 종류의 오브젝트가 많은데 하나하나 팔레트에 등록하기 번거롭다.
  • 특정 폴더의 Static Mesh를 자주 쓰는데, 매번 Content Browser에서 찾아서 배치하거나 Actor Palette에 하나씩 추가하려면 시간이 많이 든다.

그래서 이번에는 “지정한 폴더의 모든 Static Mesh를 자동으로 Actor Palette처럼 배치할 수 있는 플러그인” 을 제작했습니다.

배치할 매쉬를 지정하고 "배치 시작" 버튼을 누르면, 해당 폴더의 모든 Static Mesh가 레벨에 일괄 배치됩니다.

왜 만들었는가: Actor Palette의 장점과 한계

Actor Palette는 기본적으로 매우 훌륭한 기능입니다.

  • 자주 쓰는 액터를 빠르게 배치
  • 프로젝트별 팔레트 구성 가능
  • 드래그 한 번으로 레벨에 배치 가능

하지만 한계도 분명합니다.

  • 등록이 수동 : 매번 Static Mesh / Blueprint를 직접 Palette에 추가해야 한다
  • 유지보수 어려움 : 폴더에 새로운 자산이 추가될 때마다 팔레트 갱신 필요
  • 대규모 작업에 부적합 : 수십-수백 개의 오브젝트를 일일이 등록하는 것은 현실적이지 않음

특히 우리처럼 프로덕션에서 ‘배경 프랍’을 폴더 단위로 관리하고, 수백 개의 Static Mesh 자산을 사용하는 팀에서는 힘든 방식이었습니다.

그래서 목표는 단순했습니다.

액션 팔레트를 만들때 한번에 많은 오브젝트를 자동으로 등록할 수 있으면 좋겠다.

플러그인 설계 방향

플러그인의 요구사항은 아래 네 가지로 정리할 수 있습니다.

  • 특정 폴더를 지정
: /Game/Props/Environment/Trees
→ 이 폴더 안의 모든 Static Mesh를 가져온다.
  • 레벨에 자동 스폰
스폰 위치는 레벨에서 선택된 액터의 위치를 기준으로 한다.
  • 배치 간격과 시작 위치, 한줄에 배치할 메쉬 개수를 설정할 수 있도록
start_row: 시작 row 번호 (0부터 시작)
per_row: 한 줄에 배치할 메쉬 개수
spacing_cm: 그리드 간격 (cm)
  • 빠른 작업성
Content Browser에서 폴더 우클릭 → “Spawn Meshes Here”
Options 다이얼로그에서 옵션 설정 후 확인
  • 아티스트가 쉽게 사용 가능
파이썬 플러그인으로 제작하여 복잡한 컴파일과정 및 C++ 설정 불필요

복잡한 기능은 숨기고 단순한 UX 제공

플러그인 구현

플러그인은 Unreal Engine의 파이썬 API를 활용하여 구현했습니다.

주요 기능은 다음과 같습니다.

  1. 폴더 선택: Content Browser에서 우클릭 메뉴를 통해 폴더를 선택할 수 있도록 구현

def _get_selected_content_path() -> str:
    selected_path = unreal.EditorUtilityLibrary.get_current_content_browser_path()
    if selected_path:
        _log(f"selected content path: {selected_path}")
        return str(selected_path)
    else:
        raise Exception("NOT FOUND PATH")

  1. Static Mesh 검색: 선택한 폴더 내의 모든 Static Mesh
def list_static_mesh_assets(root: str) -> List[unreal.AssetData]:
    arm = unreal.AssetRegistryHelpers.get_asset_registry()
    flt = unreal.ARFilter(
        package_paths=[unreal.Name(root)],
        recursive_paths=True,
        class_paths=[unreal.StaticMesh.static_class().get_class_path_name()]
    )
    return arm.get_assets(flt)
  1. 배치 위치 계산: 선택된 액터의 위치를 기준으로 배치 위치를 계산
def get_selected_actor_origin():
    selected = unreal.EditorLevelLibrary.get_selected_level_actors()
    if not selected:
        return None, None, 0.0

    actor = selected[0]
    loc = actor.get_actor_location()
    rot = actor.get_actor_rotation()

    bounds_origin, bounds_extent = actor.get_actor_bounds(only_colliding_components=False)
    top_z = bounds_origin.z + bounds_extent.z

    return unreal.Vector(loc.x, loc.y, top_z), rot, bounds_extent
  1. 액터 스폰: 계산된 위치에 Static Mesh 액터를 스폰
  x = col * spacing_cm
  y = row * spacing_cm

  loc = unreal.Vector(origin.x + x, origin.y + y, origin.z)
  rot = unreal.Rotator(0.0, base_yaw, 0.0)

  actor = unreal.EditorLevelLibrary.spawn_actor_from_class(
    unreal.StaticMeshActor, loc, rot
  )
  1. 옵션 다이얼로그: 배치 옵션을 설정할 수 있는 다이얼로그 구현
@unreal.uclass()
class PlacementOptions(unreal.Object):
    start_row = unreal.uproperty(int)
    per_row = unreal.uproperty(int)
    spacing_cm = unreal.uproperty(float)

def _get_placement_options():

  obj = PlacementOptions()
  obj.start_row = 0
  obj.per_row = 5
  obj.spacing_cm = 1000.0

  options = [True, False, False, 300, 120, 1.0]

  result = unreal.EditorDialog.show_object_details_view(
      "Placement Options",
      obj,
      options
  )

플러그인 사용법

아래 GIF는 플러그인의 실제 사용 예시입니다.

플러그인 사용 예시
  • 그림 1: 플러그인 사용 예시
플러그인 사용 배치된 모습
  • 그림 2: 플러그인 사용해서 배치한 모습
아래 이미지는 Actor Palette를 사용하는 모습입니다. 엑션 팔레트 사용
  • 그림 3: 엑션 팔레트 사용

마무리

이번 플러그인 개발을 통해 Actor Palette의 장점을 살리면서도, 대규모 Static Mesh 배치를 자동화할 수 있었습니다. 아티스트들은 이제 폴더 단위로 자산을 관리하면서도, 빠르게 레벨에 배치할 수 있게 되었습니다. 이 플러그인은 리얼드로우의 웹툰 배경 제작 워크플로우에 큰 도움이 되었으며, 앞으로도 언리얼 엔진의 다양한 기능을 활용하여 생산성을 높이는 도구를 계속 개발할 예정입니다.

참고