유니티 스크롤 드래그 - yuniti seukeulol deulaegeu

마우스 포인터를 활용, 해당 오브젝트를 선택한 상태에서 움직일 수 있게 한다.

마우스 버튼이 눌리고 있는 동안에, 매 프레임마다 호출됩니다.

Ref.

Unity - 스크립팅 API: MonoBehaviour.OnMouseDrag()

Success! Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable. 닫기

docs.unity3d.com

Suggest a change

Success!

Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.

Close

Submission failed

For some reason your suggested change could not be submitted. Please <a>try again</a> in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.

Close

Your name Your email Suggestion*

Cancel

Switch to Manual

Description

OnMouseDrag is called when the user has clicked on a Collider and is still holding down the mouse.

OnMouseDrag is called every frame while the mouse is down.

This function is not called on objects that belong to Ignore Raycast layer.

This function is called on Colliders marked as Trigger if and only if Physics.queriesHitTriggers is true.

OnMouseDrag can be a co-routine, simply use the yield statement in the function. This event is sent to all scripts attached to the Collider.

NGUI 무료버전2.7.0 (2014.7. 21 기준)에서는 Scroll View 컴포넌트가 없었다. (내가 못찾은것일지도...)

1. UI Root 하위의 Panel 을 선택

2. 이름을 mainMenu로 변경

3. Component - NGUI - interaction - Scroll view 를 선택

========================================================================

Movement : 패널을 스크롤 할 수 있는 방향을 지정한다.

Drag Effect : 패널을 드래그할 때 자연스러운 멈춤효과를 재현하기 위한 효과선택

Scroll wheel Factor :  마우스 스크롤 휠로 패널의 Y축 상에서 드래그하려고 할 때, 이 곳에 0이상으 ㅣ값을 입력한다.

Momentum Amount : 패널을 드래그해서 놓았을 때 적용할 탄련을 의미

Reset Position : 코드에 의해 스크롤 뷰의 위치를 초기화 할때 스크롤 뷰가 되돌아올 위치를 지정한다.

Restrict within Panel : 스크롤 뷰의 내용이 스크롤 뷰 영역을 벗어나지 않게 제한한다.

Cancel Drag if fits : 스크롤 뷰의 내용이 스크롤 뷰 영역을 벗어나지 않게 제한한다.

Smooth Drag Start : 드래그를 시작할 때 패널이 건너 뛰는 현상을 피한다.

IOS Drag Emulation  클리핑 영역을 넘어갈 때 드래그 되는 속력이 감소한다.

Show Condition : 언제 스크롤바를 보여줄 것인지 조건을 선택한다.

==============================================================================

드래그패널

UIPanel 을 드래그할 수 있는 패널로 만들기 위해 UI Scroll view 컴포넌트를 추가했다. 이제 MainMenu를 드래그 할 수 있는 내용을 담은 게임오브젝트로 만들어야한다.

사용자가 패널을 클릭해서 드래그하려면 BoxCollider 컴포넌트가 필요하다.

1. MainMeunu 게임오브젝트를 선택한다.

1.UIPanal의 Clipping 파라미터에서 Alpha Clip을 선택한다.

2. Clipping 에 있는 size 필드에 1920, 1080dmf dlqfurgksek.

3. UIScroll view에서 IOS Drag Emulation 옵션을 해제한다.

2. Component - NGUI - inteaction - Drag Scroll view를 선택해서 MainMenu게임오브젝트에 UI  Drag Scroll 컴포넌트를 추가한다.

3. NGUI - Attach - Collider 를 선택해서 Box Collider 를 추가한다.

1. is Trigger 옵션이 체크되어있는지 확인한다, 충돌거리까지는 필요없다. UICamera의 레이캐스트를 감지하기 위한 트래거면 충분하다.

2. center 에는 0, 395, 0 을 입력한다.

3. size 에는 1300, 62, 1 을 입력한다.

오직 X축으로만 창을 드래그 할 수 있다.

메인 메뉴의 창을 자유롭게 드래그 할수 있도록 수정해본다. 

1. Main<enu 게임오브젝트를 선택한다.

2. UIScroll view컴포넌트와 MoveMent를 Unrestricted로 바꾼다.

메뉴창을 화면밖으로 드래그한다음 마우스 번튼을 놓으면 창이 다시화면안으로 들어온다. Restrict withinanel 옵션에 의한 것이다. 

유니티 스크롤 드래그 - yuniti seukeulol deulaegeu
한이터2021. 7. 28. 12:47

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 등..)를 다 먹어버려서 하나도 작동하지 않는 상황.

유니티 스크롤 드래그 - yuniti seukeulol deulaegeu

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

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

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

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

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

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

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

유니티 스크롤 드래그 - yuniti seukeulol deulaegeu

상점 화면이다. 우측의 스크롤뷰를 통하여 아이템을 구경하고 구매하는 것이다. 촌스러워서 추후 수정예정.. 흑흑 일이 많다..

유니티 스크롤 드래그 - yuniti seukeulol deulaegeu

방법 1의 문제점!! 스크롤뷰 바깥에서도 선명한 저 콜라이더..

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

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

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

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

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

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

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

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

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

유니티 스크롤 드래그 - yuniti seukeulol deulaegeu

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까지 로그가 제대로 뜨는지 확인해보자!

유니티 스크롤 드래그 - yuniti seukeulol deulaegeu

ScrollView안에 ScrollRect 컴포넌트가 존재한다. 이 ScrollRect를 저 ParentSR 변수에 넣는것이다!

유니티 스크롤 드래그 - yuniti seukeulol deulaegeu

해당 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 등으로 이름을 알아올 수도 있다. 확인할 때 편함..!

유니티 스크롤 드래그 - yuniti seukeulol deulaegeu

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

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

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

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

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

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

유니티 스크롤 드래그 - yuniti seukeulol deulaegeu

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

유니티 스크롤 드래그 - yuniti seukeulol deulaegeu

빠밤~ 추가완료!!

최종 완료 영상~!

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

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

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

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

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

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