Programing/Unity(C#)

[Unity] 버튼 위에서 드래그 시, 드래그 이벤트가 막히는 문제

hye3193 2024. 2. 12. 00:26

스크롤뷰에 버튼들을 넣고 게임을 실행시켜 보니, 버튼들의 위에서는 스크롤뷰가 제대로 스크롤 되지 않았다

 

원인은 버튼 오브젝트에 BindEvent를 통해 터치 이벤트를 구현하는 과정에서 UI_EventHandler 컴포넌트에서 상속받았던 IDargHandler 였다

 

Drag 기능을 쓰지 않음에도 해당 컴포넌트에 IDragHandler가 들어가 있어 버튼 오브젝트가 DragEvent를 가로챈 것이다

public class UI_EventHandler : MonoBehaviour, IPointerClickHandler, IDragHandler

 

그냥 IDragHanlder를 상속받는 부분을 지우고, 핸들러 관련된 코드를 지워주면 정상적으로 버튼 부분을 드래그 해도 전체 슬라이더가 스크롤 된다

 

만일 한 게임 내에서 클릭과 드래그 이벤트가 전부 필요한데, 위와 같은 문제에 직면하게 될 상황이라면

UI_EventHandler 한 개에서 ui event를 전부 다 처리하지 말고 UI_ClickEventHanlder, UI_DragEventHandler 등으로 나누어 받아도 괜찮을 것 같다

public class UI_ClickEventHandler : MonoBehaviour, IPointerClickHandler
{
    public Action<PointerEventData> OnClickHandler = null;

    public void OnPointerClick(PointerEventData eventData)
    {
        if (OnClickHandler != null)
            OnClickHandler.Invoke(eventData);
    }
}

이벤트 핸들러는 이런 식으로 작성하고

 

public static void BindEvent(GameObject go, Action<PointerEventData> action, Define.UIEvent type = Define.UIEvent.Click)
{
    switch (type)
    {
        case Define.UIEvent.Click:
            UI_EventHandler clickEvt = Util.GetOrAddComponent<UI_ClickEventHandler>(go);
            clickEvt.OnClickHandler -= action;
            clickEvt.OnClickHandler += action;
            break;
        case Define.UIEvent.Drag:
            UI_EventHandler dragEvt = Util.GetOrAddComponent<UI_DragEventHandler>(go);
            dragEvt.OnDragHandler -= action;
            dragEvt.OnDragHandler += action;
            break;
    }
}

UI_Base 스크립트에서의 BindEvent 부분은 이런 식으로 바꿔서 쓰면 된다

 

 

+) 만약 이벤트 핸들러에서 drag 부분을 제거하지 않고 이벤트를 전달하려면 아래와 같이, 자식 오브젝트에서 받은 드래그 이벤트를 부모(scroll view의 scroll rect로) 오브젝트로 전달해주면 된다

출처: https://higatsuryu9975.tistory.com/10

public class SubItem_Button : UI_Base, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    ScrollRect scrollRect;

    private void Awake()
    {
        scrollRect = {scrollView 경로}.GetComponent<ScrollRect>();
    }
    
    public void OnBeginDrag(PointerEventData eventData)
    {
        scrollRect.OnBeginDrag(eventData);
    }
    public void OnDrag(PointerEventData eventData)
    {
        scrollRect.OnDrag(eventData);
    }
    public void OnEndDrag(PointerEventData eventData)
    {
        scrollRect.OnEndDrag(eventData);
    }
}