2. Galaxy Card/3. 기타 개발

모바일 최적화 #1 (카드 터치, 드래그)

DOlpa_ 2025. 11. 25. 23:13
728x90

 

드디어 모바일에서도 게임이 작동되는것을 확인했다!!!!

 

하지만...갤볼에서 그렇게 고생했으면 이번엔 안할줄 알았는데...

역시 이번에도 PC와 모바일 환경에서 이런저런 차이가 많이 보였고

최적화 아닌 최적화를 좀 해야할것 같다

 

우선 첫번째. 클릭!

PC버전에서는 카드를 클릭하거나 드래그하는 부분들이 다 한번에 말을 알아듣고 작동했지만

모바일버전에서는 3,4번을 터치해야 한번 될까말까하게 답답하게 작동되었었다

 

 

원인을 알고보니 바로 모든 클릭에 관련된 동작들을 OnMouseDown/ Up 으로 관리하고 있던것

 

유니티는 이 메서드들을 마우스 이벤트 기반으로 만들어놔서, 모바일의 터치 입력과 완벽하게 1:1 매칭이 안된다고 한다.

그리고 더 중요한 건 OnMouseDown 계열은 절대 모바일에 최적화된 입력 방식이 아니다.

공식 문서에서도 “간단 테스트용”으로만 쓰라고 되어 있음.

 

그럼 어떤걸 사용해야 하냐?

 

IPointerDownHandler
IPointerUpHandler
IPointerClickHandler
IDragHandler 

 

▶ 100% 모바일에서도 즉시 반응함.
▶ 클릭 영역도 EventSystem(UI) 기준으로 정확하게 잡힘.
▶ 마우스/터치 모두 대응.

 

명심하자 모바일 환경에서 게임을 낼거면 OnMouseUp/Down은 사용하는게 아니다

유니티 공식문서에서도 이건 그냥 테스트용으로만 사용하라고 한다. 

 

그래서 PC 버전에서는 OnMouse를 사용하나? 했더니 그것도 아님!!!

 

IPointerDownHandler
IPointerUpHandler
IPointerClickHandler
IDragHandler 

 

거기도 이걸 쓰라고 권장한다

 

아니 그럼 도대체 OnMouse는 왜 존재하는건데??를 지피티에게 물어보니

 

 

...그렇다고 한다

 

아무튼 이것에 대해서는 새로 글을 하나 써서 정리하는게 낫겠다

 

    void Update()
{
    if (Input.GetMouseButtonDown(0))  // 모바일 터치도 이걸로 인식됨
    {
        Vector2 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        RaycastHit2D hit = Physics2D.Raycast(pos, Vector2.zero);

        if (hit.collider != null && hit.collider.gameObject == gameObject)
        {
            // 원래 OnMouseDown에서 하던 로직만 그대로 넣으면 됨
                    if (!isMouseOver) return;
        soundManager2.PlayCardSound();
        isDragging = false;
        isDragStarted = false;
        mouseDownPosition = mainCamera.ScreenToWorldPoint(Input.mousePosition);
        dragOffset2D = Vector2.zero;
        StopCurrentAnimation();
        
        // 클릭 시 가장 위 레이어로 이동
        spriteRenderer.sortingOrder = 10;
        }
    }
        if (Input.GetMouseButtonUp(0))
    {
        if (IsMyObjectTouched())
        {
            if (isDragging)
        {
            isDragging = false;
            isDragStarted = false;

            // 카드 재배치 (드래그가 끝난 후에만 재배치)
            // deckManager.RearrangeCards(this); // this 매개변수 제거
            
            // 선택된 상태에 따라 Y 위치 결정
            Vector3 targetPosition = originalPosition;
            if (isSelected)
            {
                targetPosition.y = -2f; // 선택된 상태의 Y 위치
            }
            else
            {
                targetPosition.y = -2.5f; // 기본 Y 위치
            }
            
            // 부드러운 이동을 위해 DOTween 사용
            StopCurrentAnimation();
            transform.DOMove(targetPosition, 0.2f).SetEase(Ease.OutQuad)
                .OnComplete(() => {
                    // 이동이 완료된 후 originalPosition 업데이트 (Y 위치는 유지)
                    originalPosition = transform.position;
                });
        }
        else if (isMouseOver) // 클릭 이벤트 처리
        {
            // 클릭이었다면 선택/해제 처리
            if (!isSelected)
            {
                if (!deckManager.CanSelectCard())
                {
                    return;
                }
                deckManager.AddSelectedCard(this);
            }
            else
            {
                deckManager.RemoveSelectedCard(this);
            }

            isSelected = !isSelected;
            StopCurrentAnimation();

            if (isSelected)
            {
                isMovingToOriginal = false;
                isMovingToSelected = true;
                selectedPosition = originalPosition;
                selectedPosition.y = -2f;
                currentAnimation = StartCoroutine(MoveToPosition(selectedPosition));
            }
            else
            {
                isMovingToOriginal = true;
                isMovingToSelected = false;
                Vector3 targetPosition = originalPosition;
                targetPosition.y = -2.5f;
                currentAnimation = StartCoroutine(MoveToPosition(targetPosition));
            }
        }

        // 원래의 정렬 순서로 복원
        float normalizedX = (transform.position.x + 4f) / 8f;
        int newSortingOrder = Mathf.RoundToInt(normalizedX * 7);
        spriteRenderer.sortingOrder = newSortingOrder;
        }
    }

    bool nowHover = IsMyObjectTouched();

    if (!isHover && nowHover)
    {
        isMouseOver = true;
    }
    else if (isHover && !nowHover)
    {
        isMouseOver = false;
    }

    isHover = nowHover;
}
bool IsMyObjectTouched()
{
    Vector2 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    RaycastHit2D hit = Physics2D.Raycast(pos, Vector2.zero);
    return hit.collider != null && hit.collider.gameObject == gameObject;
}

 

Update문 안에 모든기능을 넣어주고

 

 

이렇게 OnMouse에 관련된 부분들은 전부 주석처리를 해주었다

이렇게 하면 컴퓨터에서도 멀쩡히 클릭이 되면서 모바일 버전에서도 카드 클릭이 잘 되는것을 확인할 수 있다 

728x90
반응형