본문 바로가기
카테고리 없음

언리얼 엔진에서 UMG 위젯의 동적 크기

by 정보모아모아 2025. 6. 26.

언리얼 엔진에서 UMG 위젯의 동적 크기 조절 문제로 인해 C++ 코드에서 사이즈를 가져올 때 겪는 혼란은 많은 개발자들이 경험하는 부분입니다. 제가 그 원인과 해결 방법을 차근차근 설명해 드릴게요.
왜 이런 문제가 발생할까요? (The "Why")
결론부터 말씀드리면, **위젯이 디자인 타임에 설정된 '원하는 크기(Desired Size)'**와 **실제 화면에 앵커에 의해 늘어나 렌더링된 '최종 크기(Cached Geometry)'**가 다르기 때문입니다.
* Desired Size (원하는 크기):
   * 이것은 위젯 에디터에서 설정한 위젯의 고유한 크기입니다. 예를 들어, 이미지 위젯이라면 원본 이미지의 해상도, 텍스트 블록이라면 텍스트 내용에 따른 크기가 됩니다.
   * 개발자님이 C++ 코드에서 일반적인 GetDesiredSize()와 같은 함수로 조회했을 때 얻는 값이 바로 이 값입니다.
   * 이 크기는 앵커나 부모 컨테이너의 영향을 받기 전의 순수한 위젯의 크기입니다.
* Cached Geometry (캐시된 지오메트리 / 실제 크기):
   * 이것이 바로 실제 화면에 그려지는 최종 결과물의 위치, 크기, 스케일 정보를 담고 있는 데이터입니다.
   * 언리얼의 Slate/UMG 시스템은 매 프레임 '레이아웃 패스(Layout Pass)'를 거칩니다. 이 과정에서 뷰포트 크기, 앵커 설정, 정렬, 패딩 등을 모두 계산하여 각 위젯을 화면 어디에, 어떤 크기로 그릴지 최종 결정합니다.
   * 개발자님이 확인하고 싶은, 앵커에 의해 화면 비율에 맞춰 쭉 늘어난 크기는 바로 이 Geometry 정보 안에 들어있습니다.
따라서 뷰포트 크기가 변해도 위젯의 Desired Size는 변하지 않기 때문에, C++ 코드에서 잘못된 함수를 호출하면 계속 초기 설정값만 가져오게 되는 것입니다.
해결 방법: 어떻게 실제 크기를 가져오나요? (The "How")
실제 렌더링된 위젯의 크기를 가져오려면 GetCachedGeometry() 함수를 사용해야 합니다. 이 함수는 위젯의 최종 레이아웃 정보가 담긴 FGeometry 구조체를 반환합니다.
C++ 코드 예시
아래는 특정 위젯(MyTargetWidget)의 실제 렌더링 크기를 가져오는 C++ 코드 예시입니다. 이 코드는 UUserWidget을 상속받은 클래스 내에서 사용한다고 가정합니다.
// 헤더 파일에 MyTargetWidget이 UPROPERTY(meta = (BindWidget))으로 선언되어 있다고 가정합니다.
// UMG 위젯의 실제 크기를 가져오려는 함수 내부

// 먼저 대상 위젯이 유효한지 확인해야 합니다.
if (MyTargetWidget)
{
    // GetCachedGeometry()는 최종 레이아웃 정보를 FGeometry 형태로 반환합니다.
    // 이 정보는 위젯이 화면에 그려진 후에만 유효합니다.
    const FGeometry& WidgetGeometry = MyTargetWidget->GetCachedGeometry();

    // GetLocalSize()를 통해 렌더링된 위젯의 실제 크기(가로, 세로)를 FVector2D로 얻을 수 있습니다.
    FVector2D ActualSize = WidgetGeometry.GetLocalSize();

    // 로그로 실제 크기를 출력해 봅니다.
    UE_LOG(LogTemp, Warning, TEXT("MyTargetWidget's Actual Rendered Size is: %s"), *ActualSize.ToString());

    // 이제 이 ActualSize 값을 사용해서 원하시는 로직을 구현하시면 됩니다.
    // 예: float ActualWidth = ActualSize.X;
    //     float ActualHeight = ActualSize.Y;
}

매우 중요한 주의사항: 호출 시점
GetCachedGeometry()는 위젯의 레이아웃 계산이 완료된 후에만 유효한 값을 반환합니다. 만약 너무 이른 시점에 호출하면 기본값(크기 0)이나 유효하지 않은 값을 얻게 됩니다.
* 호출하면 안 되는 곳:
   * Constructor (생성자): 위젯이 아직 생성만 되었을 뿐, 화면에 배치되지 않은 상태입니다.
   * NativeConstruct의 초반부: 레이아웃이 아직 계산되지 않았을 가능성이 높습니다.
* 호출하기 좋은 곳:
   * NativeTick: 매 프레임 호출되므로, 이 시점에서는 거의 항상 유효한 지오메트리 값을 가집니다. (단, 매 프레임 크기를 확인할 필요가 없다면 성능 저하의 원인이 될 수 있습니다.)
   * 사용자 입력 이벤트 함수: 버튼 클릭 등 사용자의 상호작용으로 호출되는 함수 내에서는 위젯이 이미 화면에 그려진 상태이므로 안전합니다.
   * 딜레이(Delay) 이후 또는 Timer 사용: NativeConstruct에서 굳이 사용해야 한다면, 0.1초 정도의 짧은 딜레이를 주거나 타이머를 설정하여 다음 틱 이후에 실행되도록 하면 안전하게 값을 가져올 수 있습니다.
요약
| 구분 | Desired Size (GetDesiredSize) | Cached Geometry (GetCachedGeometry) |
|---|---|---|
| 의미 | 위젯의 고유한/기본 크기 | 앵커 등을 반영한 실제 렌더링 크기 |
| 특징 | 앵커, 뷰포트 크기 변경에 영향받지 않음 | 앵커, 뷰포트 크기 변경에 따라 동적으로 변함 |
| 사용 함수 | GetDesiredSize() | GetCachedGeometry().GetLocalSize() |
| 주의점 | 실제 화면 크기와 다를 수 있음 | 레이아웃 패스 이후 (예: Tick)에 호출해야 함 |
이 개념만 잘 이해하시면 앞으로 UMG 위젯의 크기나 위치를 다루는 C++ 코드를 작성하실 때 훨씬 수월해지실 겁니다. 혹시 추가로 궁금한 점이 있으시면 언제든지 다시 질문해 주세요!