Unity 내일배움캠프 TIL 1102 | ScrollView의 Click Event가 동작하지 않을 때 | ScrollView 위치 초기화

cheeseonrose·2023년 11월 2일
0

Unity 내일배움캠프

목록 보기
69/89
post-thumbnail

💡 ScrollView와 Click Event

☕ 문제점

  • 최종 프로젝트를 진행하던 중, ScrollView를 이용해 인벤토리를 구현하는 과정에서 ScrollView가 동작하지 않는 현상이 발생했다.
  • 정확히는 ScrollView 내부의 Slot 위에서 드래그를 하면 동작하지 않는 것이다!
  • 해당 문제에 대해 검색한 결과, Slot에게 전달된 event를 ScrollRect로 전달하는 해결 방법을 찾았다.
    해결 방법을 살펴보기 전, ScrollRect에 대해 간단하게 정리하고 넘어가자!

🍷 ScrollRect

  • 콘텐츠를 스크롤하는 기능을 제공하여, 공간을 많이 차지하는 콘텐츠를 작은 영역에 표시해야 할 때 활용할 수 있다.
  • 프로퍼티
    • Content : 스크롤 될 UI 요소들

      • ScrollView를 생성하면 하위에 Viewport - Content가 있는 것을 볼 수 있는데, Content 하위에 ScrollView에 보여줄 요소들을 넣게 된다.
    • Horizontal / Vertical : 수평/수직 스크롤의 활성 여부

    • MovementType : 스크롤 동작의 관성

      타입설명
      Unrestricted콘텐츠가 스크롤 영역 가장자리에 도달하면 튕기지 않고
      계속 움직여서 영역 밖으로 나가게 된다
      Elastic콘텐츠가 스크롤 영역 가장자리에 닿으면 튕기게 된다
      Clamped콘텐츠가 스크롤 영역 가장자리에 도달했을 때, 관성 없이 바로 멈추게 된다
    • Horizontal Scrollbar / Vertical Scrollbar : 수평/수직 스크롤 바 요소

    • Visibility : 스크롤 바를 사용하지 않을 때, 자동으로 숨길 것인지 혹은 선택적으로 Viewport를 확장할 것인기 결정


🍸 문제 해결

  • Slot UI에서 Click Event를 먼저 받기 때문에, 해당 Event가 ScrollView까지 전달되지 않는 것이었다.
  • 해당 문제를 IDragHandler를 사용해 해결하였다.
public class UI_Slot : UI_Base,
IBeginDragHandler, IDragHandler, IEndDragHandler
{
	private ScrollRect _scrollView;
    
    ...      	

	public void SetScrollRect(ScrollRect scrollRect)
    {
        _scrollView = scrollRect;
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        _scrollView.OnBeginDrag(eventData);
    }

    public void OnDrag(PointerEventData eventData)
    {
        _scrollView.OnDrag(eventData);
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        _scrollView.OnEndDrag(eventData);
    }
}
  • 우선 Slot의 컴포넌트 스크립트가 IBeginDragHandler, IDragHandler, IEndDragHandler 인터페이스를 구현하도록 한다.

  • ScrollView의 ScrollRect 컴포넌트를 참조한 뒤, 각 인터페이스의 메서드 내부에서 Event를 ScrollRect로 전달하도록 구현하였다.

    • 스크립트를 살펴보면, ScrollRect도 해당 인터페이스들을 구현한다.
  • Slot 오브젝트의 경우, Resources 폴더에서 프리팹을 불러와 실행 중 생성하도록 만들었기 때문에 인스펙터 창에서 ScrollRect를 할당하는 것이 불가능하다.

  • 따라서 해당 ScrollView를 관리하는 상위 오브젝트인 UI_Inventory의 컴포넌트 스크립트에서 ScrollRect를 참조하고, 이를 Slot으로 넘겨주도록 구현했다.

    // UI_Inventory
    _slotList[i].SetScrollRect(_scrollRect);
    // UI_Slot
    public void SetScrollRect(ScrollRect scrollRect)
     {
     	_scrollView = scrollRect;
     }

그리고 마참내 ScrollView가 동작하였다!

이렇게 해서 문제 해결!! 짜잔!



🍹 번외 - ScrollView 위치 초기화

  • ScrollView를 구현하면서 추가적으로 생각난 기능이 있는데, 바로 ScrollView 위치 초기화이다.

  • 내가 구현하는 인벤토리는 여러 개의 탭으로 이루어져 있지만 하나의 ScrollView를 공유하는 방식이다.
    따라서 이전 탭에서 스크롤했던 위치가 탭을 변경해도 그대로 남아있게 되기 때문에 스크롤 위치를 초기화하기로 했다.

  • 탭이 변경될 때마다 RectTransform의 anchoredPosition 값을 변경해주었다!

    
    private void Awake()
    {
    	_scrollViewRectPosition = _scrollViewContainer.anchoredPosition.x;
      
      	...
    }
    
    private void ChangeTab(InventoryType type)
    {
    	_scrollViewContainer.anchoredPosition = new Vector3(_scrollViewRectPosition, 0, 0);
      
      	...
    }

출처 - Unity Documentation 스크롤 사각 영역
출처 - [Unity] 스크롤(Scroll/Scrollrect) 구현하기
출처 - ScrollView(ScrollRect)와 Button의 드래그/스크롤(OnDrag)에 대한 문제 해결법
출처 - [solved] Unity Scroll View position initialize



끗~~~!

0개의 댓글