UnrealEngine/UMG

[UE5] UScrollBox에 버튼이 들어있는 위젯 스크롤이 안될 때

H프레임 2023. 1. 26. 23:27

UMG를 만들어서 확인하는데 ScrollBox 혹은 UListview와 같은 스크롤 기능이 있는 위젯에서 갑자기 스크롤이 되지 않는 경우가 생겼다. 마우스 휠을 움직이면 스크롤이 되는데 마우스 클릭후에 움직이려니 간헐적으로는 스크롤이 되는데, 계속 스크롤이 되지 않는 현상이 발생해서 원인을 찾아봤다.

 

원인은 버튼이 클릭되었음을 인지 하기 위한 이벤트 처리와, 스크롤박스의 스크롤이 되기 위한 조건 응답이 충돌하기 때문이었다. 

 

Button detail에 Advanced라는 카테고리에서 Click Method, Touch Method 세팅을 알맞는 방법으로 바꾸었더니 해결됐다. 자세한 내용은 아래에..

 

 

내가 만들고 있는 위젯은 상품의 종류를 나열해 보여줄 수 있는 리스트다. 아직 리소스도, UI 구성도 없지만 기능 테스트를 우선 하려고 작업하고 있었다.

 

ScrollBox에 넣은 커스텀 위젯은 UButton을 포함하고 있는 위젯이다.

 

클릭도 되어야하고, 스크롤박스에 들어가 있기 때문에 스크롤 이벤트가 발생하면 당연히 클릭 이벤트는 무시되고 위 아래로 움직이기만 해야한다. (이것이 목적)

 

 

UButton에는 Click, hover, Press의 이벤트에 대한 처리를 할 수 있도록 되어있는데, 이와 같은 이벤트를 인식하기 위해서 어떤 형태의 인풋이 들어와야 하는가에 대한 세팅을 하는 곳이 있다. 

 

 

 

Button_Item의 Detail에 Advanced라는 곳을 펼쳐보면 Click Method TouchMethod PressMethod가 보일 것이다. 디폴트로 Down and Up이 세팅되어 있다. 즉, Click이라는 이벤트가 발생하기 위해서는 마우스를 눌렀다가 위로 뗐을 때, 그 이벤트가 발생을 한다는 뜻이다. 

 

이 세팅이 왜 스크롤박스와 충돌이 됐을까? 너무 궁금해서 내부를 조금 더 살펴봤다.

UScrollBox가 작동하는 원리는 마우스 버튼 클릭과 움직임에 있다. UWidget은 SWidget을 래핑하고 있는데, 실질적 기능은 SWidget을 확인해야 알 수 있으므로 SScrollBox를 확인해봤다.

 

깊게 확인해 본 함수는 아래의 세 개였다.

 

1. FReply SScrollBox::OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) 함수

 

2.FReply SScrollBox::OnMouseButtonUp( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) 함수

 

3.FReply SScrollBox::OnMouseMove( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) 함수

 

스크롤이 되기 위해서는 터치가 되었다는 조건이 필요했다. TouchEvent에 값이 있을 때 mouse move에서 마우스가 움직인 만큼 계산이 들어가고 그 offset을 조절해서 스크롤을 하도록 하고 있다. 

 

여기서, 스크롤이 되기 위해 touch 되었다는 응답을 받아야하는데 마우스 버튼 down 에 대한 응답을 button이 먼저 붙잡고 있어서 스크롤박스에 그 응답이 전해지지 않은 것 같다. 결국 버튼에 응답이 들어가 버튼에서는 우선 Down 이벤트가 불렸으니 MouseButtonUp이 될 때까지 ClickMethod에 응답도 없고, 스크롤 박스는 버튼한테 우선권을 빼앗긴건지 계산을 할 기미도 보이지 않았다. 

 

그래서 해결한 방법은 Click Method와 Touch Method 세팅에 변화를 주는 것이다.

 

 

SButton으로 들어가면 Slate_Begin_Args( SButton ) 에서 ClickMethod,TouchMethod ,PressMethod에 기본 DownAndUp 세팅하는 곳을 찾을 수 있는데 각 Method마다 enum 타입이 존재한다.

 

 

 

EButtonClickMethod를 예시로 찾아보았다.

친절하게 주석으로 설명을 써두었는데, 내가 변경한 PreciseClick에 대한 설명을 보면,

 

리스트 안에서 버튼을 정확하게 눌렀을 때만 "클릭"이 된다고 적혀있다.  만약 포인터를 움직이게 되면 리스트가 스크롤 될 것이고 드래그 드롭 버튼도 허용된다.  라고 친절하게 설명해뒀다.

 

그래서 정리하자면,

 

스크롤박스, 리스트뷰, 랩박스 등! 스크롤 기능을 하는 위젯 안에 버튼이 포함된 위젯을 넣은 경우, 버튼의 ClickMethod, TouchMethod 세팅을 PreciseClick으로 변경해주어야 스크롤이 정상적으로 동작한다.  (참고로 PC보다 모바일에서 확연히 문제가 두드러진다고 하니 UI세팅 옵션도 잘 확인해봐야겠다.)

 

만약, 이렇게 했는데도 동작을 안한다면, 혹시.. 버튼의 visibility가 잘못 된 건 아닌지, 또는 버튼을 포함하고 있는 위젯의 visibility가 잘못 세팅되지는 않았는지 확인해보자.

 

런타임 중이라면 위젯 리플렉터를 활용하자