히가츠류의 보금자리

ScrollView(ScrollRect)와 Button의 드래그/스크롤(OnDrag)에 대한 문제 해결법 본문

Programming/Unity 2D

ScrollView(ScrollRect)와 Button의 드래그/스크롤(OnDrag)에 대한 문제 해결법

HiGaTsu Ryu 2021. 4. 25. 21:22

 평화로운 어느 날.. 또 다시 버그인지 뭔지.. 아무튼 문제가 생겼다.

차분히 코코아를 홀짝이며 해결하기 위해 정말 많은 검색을 했다..

 

"스크롤뷰 안에 버튼 때문에 드래그가 안됨."

"ScrollView Not Working In Button"

"unity raycast target give to behind"

"Button을 포함하고 있는 ScrollView의 스크롤"

... 등등 40종류 넘게 검색한 것 같다...

 

문제 상황부터 말하자면, Button이 raycast target을 통해서 마우스와 관련된 이벤트를 다 냠냠 먹고있었던 것이다.

뒤에 있는 ScrollView는 앞에 있는 Button이 이벤트(Click, Drag, Exit 등..)를 다 먹어버려서 하나도 작동하지 않는 상황.

 

Button 컴포넌트 만으로 "간단히" 작동하기 위해서는 "Raycast Target"이 꼭 필요하다.    (물론 그냥 Collider와 Raycast를 이용해도 되지만.. 그러면 귀찮을 것 같았다..)

나에게 주어진 해결방법은 2개 였는데...

 

[방법 1] :  Button의 Raycast Target을 끄고, Collider를 넣는다. 그 다음 마우스 클릭시 Raycast를 발사하여, Tag를 구분해서 버튼을 누르면 실행되어야하는 함수를 부른다! raycast target이 꺼져있으니, 그 뒤에있는 ScrollView는 자연스럽게 작동한다.

[방법 2] :  Button에게 전달된 event를 뒤에 있는 ScrollView에게 넘긴다.

 

나는 이 중에서 방법 2를 고르기로 하였다.

왜냐하면 콜라이더를 넣으면 ScrollView 바깥에서 가려진 Button도 클릭이 가능하기 때문이다..

아래 그림을 보면 이해가 가능하다.

상점 화면이다. 우측의 스크롤뷰를 통하여 아이템을 구경하고 구매하는 것이다. 촌스러워서 추후 수정예정.. 흑흑 일이 많다..
방법 1의 문제점!! 스크롤뷰 바깥에서도 선명한 저 콜라이더..

분명히 아무것도 없는 스크롤뷰 하단을 클릭했는데 아이템이 구매되면.. 유저 입장에서는 그저 당황.

한 페이지에 아이템 갯수가 고정되어 정해져 있는 경우면 몰라도,

나는 위 아래로 스크롤 되므로 반으로 잘린 아이템들도 생각해야했다.

 

그래서!!!!!!!!!!!!!!!!!!

최종적으로 방법 2의 Button에서 발생된 OnDrag event를 ScrollView에 전달할 방법을 찾았다!!!!

 

바로 IBeginDragHandler, IDragHandler, IEndDragHandler를 사용하는 것이다~!!!

(글쓴이는 핸들러에 대해서 헷갈려서 삽질 계속하였다...ㅎ)

 

아래 그림과 같이 IBeginDragHandler, IDragHandler, IEndDragHandler를 추가하면

OnBeginDrag, OnDrag, OnEndDrag event를 받을 수 있다! (함수 생성 필수!!!!)

OnBeginDrag, OnDrag, OnEndDrag 에서 혹시 더 구현하고 싶은 내용이 있다면, 부담 없이 써도 괜찮다~

위처럼 OnBeginDrag, OnDrag, OnEndDrag event를 받고, ScrollView안에 ScrollRect 컴포넌트에게 넘겨준다..!!

이렇게하면 ScrollView도 Button이 받은 이벤트를 똑같이 넘겨받게 되는 것이다~

 

아래 코드를 남겨둔다! Awake 부분은 잘 바꿔서 사용하시길 바람.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class ButtonTouchHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    public ScrollRect ParentSR;

    private void Awake()
    {
        ParentSR = transform.parent.parent.parent.parent.GetComponent<ScrollRect>();
    }
    
    public void OnBeginDrag(PointerEventData e)
    {
        ParentSR.OnBeginDrag(e);
    }
    public void OnDrag(PointerEventData e)
    {
        ParentSR.OnDrag(e);
    }
    public void OnEndDrag(PointerEventData e)
    {
        ParentSR.OnEndDrag(e);
    }
}

 

그외 작동이 되지 않는 경우, 연동이 되지 않은 경우도 있다고 하니..

Debug.Log("Check"); 등을 통해 event까지 로그가 제대로 뜨는지 확인해보자!

 

ScrollView안에 ScrollRect 컴포넌트가 존재한다. 이 ScrollRect를 저 ParentSR 변수에 넣는것이다!
해당 ScrollRect 컴포넌트를 Button에게 추가해준 ButtonTouchHandler 스크립트의 변수에 잘 추가하자!

참고로 Awake에 저 끔찍해보이는 컴포넌트 할당은...

내 Button 친구들은 동적 생성이라 Inspector 창에 미리 넣어둘 수가 없어서,

transform.parent.parent.parent.parent.GetComponent<ScrollRect>();

를 Awakw에서 사용해서 생성되자마자 저 멀리 ScrollView를 찾아가서 넣어줬을 뿐,

더 편하게 ScrollRect를 가져올 방법이 있다면 그것을 쓰길 바란다. (Inspector에 드래그..라던가.)

 

transform(자신, 현재 ItemBut_Btn)

transform.parent (부모, 현재 Item_0(Clone))

transform.parent.parent (부모의 부모, 현재 Content)

transform.parent.parent.parent (..생략, 현재 Viewport)

transform.parent.parent.parent.parent (..생략 , 현재 ScrollView)

 

구현하는 사람마다 parent 단계가 다를테니, 각자 알아서 디버깅 잘 할 것!!!!!!!!!!!

transform.parent.parent.parent.parent.name 등으로 이름을 알아올 수도 있다. 확인할 때 편함..!

각자의 게임에 맞춰서 ScrollRect 변수를 채워주면 될 뿐! 나는 동적 생성이다!!

                                             스크롤을 위해 클릭 시 바로 버튼이 눌리는건, 내가 그렇게 구현해서 그렇다...!!                                              당연히 스크롤 할 때 클릭 하지 않도록도 가능하니, 그 부분은 연구하면 재밌고 좋다~

 

그러면 짜잔~ 아래 영상처럼 버튼 위에서 클릭해도 스크롤이된다~!

 

참고로 현재 드래그는 되지만, 마우스 휠은 먹지 않는다...!!!!

하지만 그냥 같은 원리로 마우스 휠 관련 IScrollHandler를 넣어주면 된다~ㅎㅎ

인터페이스.. 핸들러야.. 사랑해! 너무 편해서 좋다~

 

IScrollHandler를 추가하면, Alt+Enter 단축키나 빠른 리펙토링 구현으로 인터페이스를 구현할 수 있다~
빠밤~ 추가완료!!

최종 완료 영상~!

뒤에 뿅뿅뿅뾱뾱뾱 소리는 다른 시스템이 돌아가는 소리니 신경쓰지 않아도 괜찮다~

 

이상 스크롤뷰(ScrollView)가 버튼(Button)과 함께 잘 작동하지 않을 때

어떻게 해야 클릭, 드래그, 스크롤 할 수 있는지에 대한 글이었다!

읽어주셔서 감사드리며..

 

 

ScrollView+Button을 통해 다들 행복한 스크롤 버튼UI 생활이 되길 바랍니다~!!

★이와 관련된 새로운 방법이나 활용법은 언제든지 댓글이나 연락 부탁드립니다.

 

Comments