나만의 작은 도서관
[TIL][C++] 250820 MMO 서버 개발 83일차: [언리얼] UMG 위젯의 Visibility 속성, [언리얼] UFUNCTION 지정자BlueprintImplementableEvent, BlueprintNativeEvent, 사용 예시: GetToolTipWidget을 오버라이드 해보자 본문
Today I Learn
[TIL][C++] 250820 MMO 서버 개발 83일차: [언리얼] UMG 위젯의 Visibility 속성, [언리얼] UFUNCTION 지정자BlueprintImplementableEvent, BlueprintNativeEvent, 사용 예시: GetToolTipWidget을 오버라이드 해보자
pledge24 2025. 8. 21. 00:25주의사항: 해당 글은 일기와 같은 기록용으로, 다듬지 않은 날것 그대로인 글입니다.
[언리얼] UMG 위젯의 Visibility 속성
- 블루프린트 위젯을 만들다 보면 위젯하나가 여러 개의 컴포넌트들로 구성되며, 상황에 따라 일부 컴포넌트들이 1) 보이지 않게 하거나, 2) 보이지만 클릭은 되지 않도록 하고 싶을 때가 있다. 이럴 때 사용하는 것이 바로 Visibility 속성이다.
Visibility의 위치

- 블루프린트 위젯의 디테일 패널을 보게 되면, Behavior이라는 목록이 있고, 여기에 Visibility가 있다.
Visibility의 종류

- 위 그림과 같이 Visibility의 종류는 5개가 있고, 각 종류의 의미는 아래와 같다.
- Visible: 위젯이 화면에 보이며, 마우스 클릭, 터치와 같은 히트 테스트에 반응한다.
- Collapsed: 위젯이 화면에 보이지 않고, 공간 또한 차지하지 않는다. 부모 위젯의 경우 Collapsed로 설정된 컴포넌트를 레이아웃에서 존재하지 않는 것처럼 처리된다. (다른 위젯의 배치를 위해 공간을 확보해야 할 때 유용)
- Hidden: 위젯이 화면에 보이지 않지만, 공간은 차지한다.
- Not Hit-Testable: 위젯이 화면에 보이지만, 마우스 클릭, 터치와 같은 히트 테스트에 반응하지 않는다. 이 상태에서 두 가지 세부 옵션으로 나뉜다.
- Self & All Children: 히트 테스트 비활성화 속성을 현재 컴포넌트와 하위에 있는 모든 위젯들에게 적용한다. (재귀적 비활성화)
- (공식 문서에선 “HitTestInvisible”)
- Self Only: 히트 테스트 비활성화 속성을 현재 컴포넌트에만 적용한다.
- (공식 문서에선 “SelfHitTestInvisible ”)
- Self & All Children: 히트 테스트 비활성화 속성을 현재 컴포넌트와 하위에 있는 모든 위젯들에게 적용한다. (재귀적 비활성화)
| 속성 | 화면 렌더링 | 공간 차지 | 히트 테스트 가능 여부 | 주요 용도 |
| Visible | ✅ (보임) | ✅ (차지) | ✅ (가능) | 기본 상태, 위젯이 완전히 상호 작용 가능한 경우 |
| Collapsed | ❌ (사라짐) | ❌ (차지하지 않음) | ❌ (불가능) | 위젯을 완전히 숨기고 레이아웃 공간도 비워야 하는 경우 |
| Hidden | ❌ (사라짐) | ✅ (차지) | ❌ (불가능) | 위젯을 숨기지만 레이아웃 공간을 유지해야 하는 경우 |
| Not Hit-Testable(Self & All Children) | ✅ (보임) | ✅ (차지) | ❌ (불가능) | 위젯과 모든 자식 위젯을 클릭할 수 없게 만들어 오버레이 등으로 사용할 경우 |
| Not Hit-Testable(Self Only) | ✅ (보임) | ✅ (차지) | 위젯 자신: ❌ | |
| 자식: ✅ | 위젯 자체는 클릭 불가하지만, 자식 위젯들은 상호 작용이 가능해야 할 경우 |
자주 발생하는 실수
- 부모 컴포넌트를 Not Hit-Testable(Self & All Children)으로 해두고 자식 컴포넌트를 Visible로 해놓아도 자식 컴포넌트는 클릭이 되지 않는다.
[언리얼] UFUNCTION 지정자BlueprintImplementableEvent, BlueprintNativeEvent
- UFUNCTION에는 위와 같은 이름도 드럽게 긴 두 지정자가 있다.
이 지정자들은 뭘까?
- 간단히 말해 C++에서 사용하는 가상 함수 메커니즘을 C++과 블루프린트 사이에 적용할 때 사용하는 지정자라고 생각하면 된다.
- BlueprintImplementableEvent는 “순수 가상 함수”, BlueprintNativeEvent는 “일반 가상 함수”라고 보면 된다.
더더 자세한 설명
- 블루프린트가 C++ 클래스를 상속받은 자식 클래스라는 것을 명심하고 바라보면 이해가 쉽다.
- BlueprintImplementableEvent(줄여서 BIE)
- 네이티브 함수(C++ 함수)가 블루프린트로 통신을 보낼 수 있도록 하는 주요한 방법.
- 위 지정자를 UFUNCTION에 집어넣게 되면 해당 함수는 “순수 가상 함수”와 비슷하게 취급되기 때문에 C++ 에선 정의 부분을 구현하지 않는다.
- 정의 부분은 블루프린트에서 오버라이드 방식으로 구현할 수 있으며, 오버라이드를 하지 않을 경우 빈 함수가 작동된다.(이 부분이 오버라이드 하지 않으면 객체 생성이 불가해지는 C++가 조금 다름)
- C++ 클래스를 BP에서 상속받았을때 해당 함수는 function의 override 목록에 추가로 표시된다.
- BlueprintNativeEvent(줄여서 BNE)
- 위와 같지만, 블루프린트가 함수를 덮어쓰지 않는 경우 호출되는 함수의 기본 네이티브 구현이 있다는 점이 다르다.
- 위 지정자를 UFUNCTION에 집어넣게 되면 해당 함수는 “일반 가상 함수”로 취급되며, C++에서 정의할 수 있다.
- 블루프린트에 구현이 없는 경우 일정한 기본 동작이 있었으면 할 때 사용한다. BIE보다 비용이 더 들기에 함수성이 필요한 경우에만 사용한다.
- BNE를 덮어쓸 때 필요한 경우, 이벤트나 함수 노드에 Add call to parent를 선택하여 네이티브 구현을 호출할 수 있다.
- 블루프린트에서 오버라이드할때 Super::func()마냥 끌고와 실행시킬 수 있다는 말
- C++ 클래스를 BP에서 상속받았을때 BIE와 동일하게 function의 override 목록에 추가로 표시된다.
BlueprintNativeEvent로 지정한 함수를 C++에서 정의할 때 주의할 점
- BlueprintNativeEvent는 C++에서 정의를 할 수 있는데, 이 경우 반드시 '[선언된 함수 명]_Implementation’와 같은 이름으로 정의해야 한다.
// someClass.h
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void SomeFunction();
// someClass.cpp
someClass::SomeFunction_Implementation(){
//...
}
두 지정자 모두 주의할 점: override 키워드는 적지 않는다.
- 일반 C++에서의 가상 함수는 override 키워드를 사용하는데, 언리얼에서는 블루프린트에서 override 하기 때문인지 두 지정자를 사용할 경우 override 키워드를 적으면 안 된다.
사용 예시: GetToolTipWidget을 오버라이드 해보자
- 언리얼에서는 이미 툴팁 기능을 구현해 두었다. 문제는 이 툴팁 기능을 블루프린트에서 그냥 사용할 경우 Description만 넣을 수 있고 커스텀 위젯을 띄우는 건 안된다. 그래서 언리얼은 “커스텀 위젯을 띄우고 싶으면 이걸 써!”라고 던져준 게 있는데 그게 바로 GetToolTipWidget이다.
- GetToolTipWidget를 적절히 오버라이드 한 경우, 언리얼이 적당히 알아서 잘 툴팁을 띄웠다가 제거한다. 개발자는 그저 띄울 툴팁을 반환하는 코드를 짜면 된다.
GetToolTipWidget 오버라이드 방식을 이용한 툴팁 띄우는 방법
1 - GetToolTipWidget_Implementation을 C++에 정의한다.
- 블루프린트 위젯이 상속받는 C++ 클래스에 아래와 같이 작성하면 된다.
- 코드는 별거 없고, 그냥 CreateWidget으로 툴팁 위젯을 생성한 다음 생성한 위젯을 반환해 주는 것이다.
// SlotWidget.h
public:
/** 툴팁으로 사용할 위젯 클래스 */
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Item")
TSubclassOf<UItemTooltipWidget> TooltipClass;
protected:
/** 툴팁 반환 */
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
UWidget* GetToolTipWidget() const;
// SlotWidget.cpp
UWidget* USlotWidget::GetToolTipWidget_Implementation() const
{
if (SlotItem.TemplateId > 0 && TooltipClass)
{
UItemTooltipWidget* Tooltip = CreateWidget<UItemTooltipWidget>(GetWorld(), TooltipClass);
if (Tooltip)
{
Tooltip->Init(SlotItem); // 아이템 정보 전달
return Tooltip;
}
}
return nullptr;
}
2 - 블루프린트에서 띄울 툴팁 클래스를 설정해 준다.

- C++ 코드에서 띄울 툴팁을 설정하는 부분이 있었다.(ToolTipClass) 요거를 블루프린트 디테일 텝에서 기본값으로 미리 만들어둔 툴팁 위젯을 설정한다.
3- 컴포넌트에 ToolTipWidget 바인드

- 디자인 탭에서 툴팁을 띄울 컴포넌트를 선택하고, tooltip을 디테일 패널에서 검색한다. 여기서 바인드를 누르고 create bind를 해서 바인딩한다.
4 - 그래프 탭에서 부모 클래스의 GetToolTipWidget(그러니까 위에서 만든 C++ GetToolTipWidget_Implementation)을 호출하도록 한다.

- 대충 그래프가 이렇게 되어있으면 된다.
참고 자료
https://hyo-ue4study.tistory.com/42
https://blog.naver.com/kzh8055/222018031030
