실제 드래그 효과를 쓰려는 목적이 아니라
짧은클릭, 긴클릭 구현하는데 클릭중에 포인터 잘못움직이면 클릭이벤트 캔슬되는거 킹받아서
OnDrag()로 드래그 이벤트도 같이 받아서 클릭이벤트 보정용으로 사용하고 있거든?
근데 OnDrag를 여기서 받아버리니까 스크롤바 잡아끄는 동작이 작동을 안하네;
이벤트 데이터를 단순히 그냥 전파하거나 안받은셈 치는 메소드같은거 없음??
RayCastAll로 수동재호출 하려니까 골치아프다 ㅜㅜ 뭐가 문제인지 유니티 이벤트 시스템이 알아서 받는것만큼 알잘딱깔센 잡히지가 않음
쉬운데 Click Down/Click Up에서 포인터클릭이벤트 데이터의 위치 정보가 거의 안변했으면 긴클릭 짧은 클릭으로 인식시키고 위치정보 변동량이 크면 드래그로 인식하게끔 하면 도미
OnDrag는 안넣으면 PointerUp이 의도하지 않은 상황에서 호출되는 현상 때문에 넣은건데... 정확히는 드래그핸들러가 없는상태에서 드래그동작이 조금이라도 발생하면 클릭이벤트가 끝났다고 판단하는지 PointerUp을 자꾸 호출함
내가 말한거 의도를 잘 이해 못한거같네 내가 듣기만했을 때는 지금 구조 답 없거나 답이 있어도 불필요하게 꼬아서 작업해야할거같은데? down(시작 위치정보기록) -> Drag -> Up(끝 위치 정보 기록) 포인터 시작위치정보 끝정보 비교해서 일정 차이 이하-> 짧은 클릭 / 긴 클릭 위치정보 변동량 유의미한 변화 -> Drag 로 넘어가는 구조로 가는게 나을거같다는거임
Drag(끝 위치 정보 계속 기록) 이거 빠트렸네
음... 실제로 내가 말한 드래그 보정이 비슷한 방식으로 구현되어있는것 같은데? 결국 포인터 시작정보 끝정보 지속시간을 가져오기 위해서 IDragHandler를 넣은거임. 그랬더니 얘가 드래그이벤트를 그대로 흡수해서 원래 처리되어야할 곳으로 못가고 그대로 먹어버린다는게 문제가 된거고 문제는 드래그 이벤트 핸들링은 다른곳에서 한다는건데 어떻게 넘겨줘야 되는지 모르겠음 ScrollView쪽으로 넘겨줘야 하는데 Raycast로 스크롤뷰 찾아서 넘기려고 하는데 잘 안돼서 골머리앓는중...
IDragHandler 없이 down -> drag -> up을 추적하려고 하면, 왠지모르게 포인터가 1픽셀이라도 이동하는 순간 Up이 호출돼버려서 포인터를 얼마나 길게 잡고있었는지 얼마나 움직였는지 추적이 안됨..
그러니까 너가 말한 위치정보 변동량 유의미한 변화 -> Drag 지금 이부분을 구현하고싶은거. 드래그이벤트라고 판별은 됐는데 정작 그 판별하는 과정에서 드래그이벤트를 흡수해버려서 원래 드래그이벤트를 처리해야하는 곳에서 드래그이벤트를 못받음 ㅜ
IPointerDownHandler, IPointerUpHandler, IDragHandler 이거 세개만 상속받고 인터페이스 구현해서 써봐 그래도 안되면 코드를 올려봐 나도 저 방식으로 긴클/짧클/드래그 다 구현했는데 얘기듣다보니까 너가 짠 로직문제인거같아서 이 이상은 코드 안보고 설명이 어렵네 아니면 GPT라도 돌려보던가
void CheckOnDrag(포인터이벤트데이터 e) { if(초기 e위치 - 현재 e위치 > 설정한 변동량 크기) 드래그함수호출() } void CheckOnUp(포인터데이터 e) // 위에 if랑 같은 비슷한조건으로 긴클릭/짧은클릭 실행할지 말지 구현
음... 그러니까 드래그함수호출()이 내부적으로 처리가 안되고 다른 오브젝트로 이벤트 데이터를 넘겨서 처리해야 되는 상황임. 내부에서 돌아가는건 문제가 없는데 외부전달이 제대로 안되고 있는거고... 오브젝트를 직접 찍어서 ExecuteEvents.Execute로 이벤트데이터를 넘겨도 받는쪽에서 제대로 처리가 안되는데 이유를 모르겠네
아 밑에 저 문제 얘기였구나 저런거는 옵저버 패턴이나 이벤트버스로 처리해도 되고 scrollrect 하위 아이템을 생성하고 초기화할 때 부모 UI 캐싱해둬서 처리하면 됨
Down 시점 기록, Up 시점 기록후 UpTiming - DownTiming < value 방식으로 구분하는게 불가능한 구조임?
클릭하고 일정 시간이 지나면 바로 반응해야하면 코루틴 하나 만들어서 Down에 StartCoroutine 하고 Up에 StopCoroutine 해서 코루틴에서 프레임마다 pressedTime += time.deltaTime 돌리고 pressedTime > value 조건으로 Coroutine 내부에서 처리하는것도 될거같은데
Up시점을 제대로 기록하려면 IDragHandler를 넣어야하는데 문제는 그걸 넣는순간 얘가 드래그이벤트를 먹어버린다는게 현재 문제상황 ㅜㅜ
코루틴 방식으로 할거면코루틴 내부에 float pressedTime, bool didWork = false 변수 두개만들어서while문으로 yield return null;로 프레임마다 돌리면서pressedTime += time.deltaTime;if(!didWork %% pressedTime > (니가 원하는 길이){ Work(); didWork = true;}이렇게 해봐
%% -> &&
Up에 단순히 코루틴 종료하는 코드만 넣으면 될거같은데
그리고 드래그 기반으로 체크할꺼면 IBeginDragHandler, IEndDragHandler도 있긴 함
그 정확한 상황은 잘 모르겠는데, 네가 짠 OnDrag이벤트 코드에서 해당 이벤트가 소비되어 사라지지 않고 다른(기존) 컴포넌트에도 해당 이벤트가 전달되게 하고 싶은 거라면, 그냥 해당 컴포넌트 들고와서 직접 ~~~.OnDrag(args) 호출해주면 되긴 함 가로세로 중첩 ScrollRect같은거 구현할때 많이들 쓰는 방법임
기본적으로 유니티 이벤트 시스템은 구독하면 제일 처음 받은애가 걍 그걸 소비해버림. 네말대로 해당 이벤트를 '전파'를하고 싶으면 전파하고 싶은 대상에 직접 해당 콜백 함수를 호출해주면 됨. 이런걸 고려한건지 유니티 내장 UI 컴포넌트들은 이러한 이벤트들이 앵간하면 다 외부에서 접근 가능하거든ㅇㅇ 가로세로중첩 scrollrect같은것도 유니티에선 기본적으론 지원 안하는데 위 방식으로 구현 가능하거든. 이건 너랑은 다른 상황인건 알지만 이런식으로 이벤트 라우팅하는 예가 있다라는걸 참고하기 좋을듯 discussions.unity.com/t/nested-scrollrect/550540/9 CaptainSchnittchen답글의 OnBeginDrag쪽 코드봐보셈
정확히 그 상황입니다 형님 ㅜㅜ 근데 가장 큰 문제가 이제 그 해당 컴포넌트를 어떻게 찾아야할지인데 레이케스트 돌려서 ExecuteEvents.CanHandleEvent()로 검증해서 넘기면 될줄알았는데 ScrollRect가 CanHandleEvent false나오는거 실화입니까...? CanHandleEvent가 이럴때 쓰는게 아닌가 혹시
일단 아래에 단 댓글도 확인은 해보셈 아마 그게 근본적인 해결책일 것 같다는 생각이 들기는 하는데... 그거랑 별개로 네 접근방식대로 해결하자면, 일단 기본적으로 롱터치 가능한 버튼이 scrollrect 안에 있는데 드래그가 안되는게 문제란거면 기본적으로 그 버튼이 scrollrect의 자식으로 있을거잖아 그럼 굳이 raycast 안 써도, GetComponentInParent로 ScrollRect를 찾으면 되는 거잖아. 쓸데없이 성능 소비해가며 raycast 쓸 필요 없고 유니티 10년넘게 써오면서 CanHandleEvent란게 있는 줄도 몰랐는데 문서보니 적어도 이 상황에 쓸 건 아닌 것 같아
그냥 바로 컴포넌트 찾아서 다이렉트로 OnDrag 직접 호출해서 이벤트 넘겨버려 네 접근방식에서는 그게맞음
vs꺼져있어서 가라코드로 작성하면 void OnDrag (~~ eventData) { //니코드 var sr = this.GetComponentInParent(); if(sr != null && sr.isActiveAndEnabled) sr.OnDrag(eventData) } 걍이럼되겠지
사실 처음 테스트때 나도 제일 먼저 떠오른게 GetComponentInParent라 그걸로 했었는데 범용적으로 쓰는 커스텀 이벤트 핸들러 컴포넌트에 넣기에 적합한 코드는 아니겠다 싶어서 자동으로 찾게 만드는 기능을 알아보는 중이었음. 괜히 엉뚱한데로 드래그이벤트 튀진 않을까 하는 생각도 잠깐 했었었고... 근데 어차피 scrollrect 말고는 이벤트 전파가 필요한 상황이 없을 것 같기도 해서 그냥 이대로 갈까 고민중이기도 한데
엉뚱한데로 튀는 걸 고민한다는것 자체는 좋은 방어적 접근이라고는 생각한다만 적재적소에 사용자가 사용하냐에 따라 다르지 네가 범용적으로 사용되는 라이브러리를 만든다고 쳐도, 결국 "요구사항"내지는 "예외사항"이라는 건 존재할 수밖에 없음. 네가 전자렌지 만든다치면 네가 굳이 사용자가 계란을 전자레인지에 쳐넣고 돌려서 터지는 상황까지는 책임 안져도 된단 거임 네가 예상 가능한 범위까지만 그냥 대응하셈 네가 지금 만들고있는게 에디터 내에서 정적으로 생성만 하는 컴포넌트라면 부모오브젝트를 OnReset에서 미리 SerializedField로 캐싱해둔다던가 동적으로 이동되거나 생성될 수 있는 컴포넌트를 상정하고 있다고 한다면 부모에서 가져온 컴포넌트와의 depth를 비교해서 예외처리를 한다던가 할 수 있겠지
그리고 적어도 이런 상황에서는 더 raycast를 쓸 필요가 없고, 성능 따지면 써서도 안 됨 기본적으로 유니티 scrollrect내의 버튼은 해당 scrollrect 객체 안에 들어가있는건데 (이미 자식인게 확실함) 굳이 raycast 쓸 필요가 없잖음. GetComponentinParent가 최선은 아닐지언정 raycast보단 나아
그리고 scrollrect안에 long press 되는 버튼이 있을 경우에 대한 UX도 고찰은 해 봐야 할 듯. 버튼 크기에 따라서도 갈리겠지만 유저가 정말 길게 누르고 싶었던 건지, 아니면 그냥 드래그를 하고 싶었던건지 판별하기 위한 거 이미 그거 고찰하고 있으니까 "보정"이라는 단어를 쓴 거 같은데 알고 있을지 모르겠지만 유니티에서는 pixelDragThreshold라는 값이 하나 있음. 얼마나 드래그를 해야 드래그로 인식을 할 지에 대한 여부인데, 비교적 떨림이 덜한 PC 환경에서는 몰라도 모바일 환경에서는 거의 무조건 기기 dpi따라 좀 만져줘야 하는 값임
docs.unity3d.com/550/Documentation/ScriptReference/EventSystems.EventSystem-pixelDragThreshold.html mentum.tistory.com/298 정확한건 docs랑 이 포스트 참고해보셈 네 상황을 정확히 인지하고 있는 건 아니지만 아마 이걸 만지는게 근본적인 해결책일 가능성도 있음
아아니 선생님 상황을 아주 정확히 인지해주셨는데요 PC에서는 문제가 없었는데 모바일 넣어보니까 떨림때문에 자꾸 오작동해서 이 모든 문제가 시작된게 정확히 맞고 그런 기능도 혹시 있나 찾아보긴 했었는데 제가 넘 대충찾아본듯 합니다 ㅜㅜ 도움을 너무 많이 받아서 말이 편하게 안나오네요 복받으십쇼