본문 바로가기
Unreal/[UE4] 플랫포머 제작 연습(C++)

10. 버튼 위젯 커스텀

by 잡템 2023. 12. 8.

오늘은 기존에 만들었던 버튼을 수정해 하나의 위젯블루프린트를 재사용해서 UI를 꾸밀수있게 시도했다.

유니티 같은경우에는 프리펩을 만들어 배치한뒤 복사해서 개별적으로 인스펙터에서 수정할 수 있지만

 

언리얼의 경우엔 왼쪽 WBP_InputButton은 이미지까지 계층구조를 직접확인해서 수정할 수 있지만

이것을 다른 위젯블루프린트에서 사용할때는 오른쪽과같이 해당 위젯의 하위개체까지는 확인할 수 가 없어서

버튼을 여러개 배치하더라도 각 버튼의 이미지를 개별적으로 수정할 수 없다.

 

이런 문제를 해결하기위해서 에픽게임즈에 액션 RPG라는 샘플의 자료를 참고했다. 해당 샘플에선 버튼을 재사용하기위해 FSlateBrush타입의 변수를 따로 추가해 에디터상에서 변경이 생기면 해당 변수의 값을 이미지에 적용하도록 블루프린트로 작업이되어있었다. 샘플의 그래프는 다음과 같다.

 

이 과정을 C++로 직접 구현하기위해 똑같이 FSlateBrush를 Edit 할수 있게 변수선언해서 컴파일을 시도했으나 계속 에러가 발생해서 원인을 제대로 찾지 못해서 시간을 상당히 소비했는데 구글링으로도 따로 정보를 얻지 못해 다른방법을 선택하려다 언리얼 클라이언트 지인에게 조언을 구해서 해결할 수 있었다.

 

원인은 FSlateBrush의 경우 UMG와다른 Slate라는 커스텀 UI 프레임워크의 구조체여서

Build.cs에 "SlateCore"를 추가해줘야 했다.

//Build.cs
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG", "Niagara", "SlateCore"});

//버튼UI 헤더
UPROPERTY(meta=(BindWidget))
class UImage* Button_Image;

UPROPERTY(EditAnywhere)
FSlateBrush Button_Brush;

UPROPERTY(EditAnywhere)
FMargin Button_Margin;

 

 

이제 에디터에서 Button_Brush나 Button_Margin의 값변경시 Button_Image의 값이 변경되어야 하는데

처음에는 PostEditChangeProperty를 사용했다. 해당 함수는 에디터 전용함수로

에디터에서 타겟의 값 변경시 호출되는 함수라고한다.

#if WITH_EDITOR

void UInputButton::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
     Super::PostEditChangeProperty(PropertyChangedEvent);

     Button_Image->SetBrush(Button_Brush);
}

#endif

사용할경우 위와같이 WITH_EDITOR로 에디터에서만 사용하는 함수라고 구분지어줘야한다.

해당 함수를 사용할경우에는 WBP_InputButton에서 Brush값을 변경할때는 제대로 적용이 되고 문제가 없었지만

HUD쪽에 여러개 배치한 버튼에서 변수값을 수정시 에러가발생해서 엔진이 꺼지는 문제가 생겼다.

이문제를 어떻게 해결해야 하나 고민하다 액션 RPG샘플에서 블루프린트 작업했을때는 어떤 시점에서 호출하는지를 참고했다. 

 

그래프에서 노드를 따라가보니 Pre Construct 이벤트에서 해당과정을 호출한다는것을 알 수 있었고 이와 동일한 함수를 C++에서 사용하기위한 방법을 검색해서 찾았다

UUserWidget 에는 는 액터와 다르게 BeginPlay같은 함수가 없었고 Native라고 이름붙는 함수가 몇가지 있는데 이함수들이 위젯 생성시, 추가시, 삭제시 등에 호출되는 함수들이라고한다.

 

그 중 NativePreConstruct라는 함수가있어서 찾아봤는데 구글에선 따로 정보를얻진 못했고 gpt를 사용해서 검색해본결과

위젯이 미리 구성될때 호출되는 함수라고하며 에디터에서 편집될때와 런타임에서 위젯이 생성되기전에 호출된다고한다.

gpt의 결과를 100%신뢰할 수는없으니 완벽하다고 할 순없지만 이 정보를 바탕으로 테스트 해본결과 HUD쪽에서 수정해도 정상적으로 동작함을 확인할 수 있었다.

작업코드는 다음과 같다.

void UInputButton::NativePreConstruct()
{
    Super::NativePreConstruct();

    Button_Image->SetBrush(Button_Brush);
    Cast<UButtonSlot>(Button_Image->Slot)->SetPadding(Button_Margin);
}

 

 

다음은 레벨이동시 배경음이 처음부터 재생되는 문제를 해결할 계획이다.

 

Reference

https://koreanfoodie.me/1155