자유롭게 이동이 가능한 카드슬롯 만들기

Tom·2024년 12월 16일
0

카드게임 만들기

목록 보기
1/13

만든거 미리보기
카드게임을 만들어보기로 했다. 근데 그러려면 일단 자유로운 카드의 이동부터 만들어야겠다는 생각을 했음.

그럼 만들어 보입시더

일단 정렬을 위해 최상위 오브젝트에 LayoutGroup컴포넌트를 사용하고, 그 아래엔 슬롯들을 만들어 드래그 할 때와 그 종료시에도 그룹은 항상 일정한 간격 유지하며 정렬되어 있을 수 있도록 만들었다. 내부 오브젝트에는 유니티 이벤트 핸들러의 드래그 핸들러 인터페이스를 이용해서 드래그중 포인터의 위치로, 종료시 localPos를 0으로 간단하게 만들어봤음. 이때 가장 먼저 발생한 문제점은 뭐였냐면,
바로 하이라키 계층구조 때문에 뒤에있는 오브젝트들은 드래그시에 정상적으로 가장 전면에 랜더링되지만, 1번 카드는 2, 3, 4, 5번 모든 카드쪽으로 드래그 할 때 가장 뒤쪽에 보인다는 것이었음. 이건 간단하게 슬롯 바깥쪽에 새로운 부모를 만들어두고 드래그 시작시에 부모를 그쪽으로 옮겨주는것으로 해결했다.

private Transform dragParent;
private CardSlot originalSlot;

private void OnPointerDownCard(DraggableUIObject drag)
{
    originalSlot = drag.transform.GetComponentInParent<CardSlot>(); //이건 돌아갈 때 원래 위치로 돌아가기 위해 저장해놨다.
    drag.transform.SetParent(dragParent);
}

하이라키에선 저렇게 슬롯그룹 외부로 빼두어 가장 드래그중인 오브젝트가 화면 가장 위쪽에 위치할 수 있도록 했다.

드래그중인 오브젝트의 위치에 따라 나머지 오브젝트들도 정렬하기

사실 이건 발라트로를 보고 만들어봐야겠다고 마음먹었다. 발라트로는 카드를 드래그중일 때 드래그중이지 않은 나머지 카드들도 드래그중인 카드의 영향을 받아 자동으로 정렬이 된다. 참으로 만족스러운 피드백인데, 이런게 있으면 따라 안만들어 볼 수 없지. 일단 드래그중인 카드의 x좌표값을 나머지 카드들과 비교해서, 커지거나 작아질 경우 비어있는 슬롯으로 부모를 옮기면 될 것 같다고 생각했다.

public class CardSlot
{
	public bool isEmpty { get {return transform.childCount == 0; } }
}

일단 슬롯 외부에서 빈 슬롯인지 확인하기 위해 자식의 개수로 슬롯이 현재 차있는지 확인한 후, 상위 그룹에서 슬롯 배열을 순회하며 현재 드래그중인 카드의 x값과 슬롯에 있는 카드들의 x값을 비교해주기로 했다.

    private void OnDragCard(DraggableUIObject drag)
    {
        float draggingCardX = drag.transform.position.x; // 현재 드래그중인 카드의 x좌표

        for (int i = 0; i < cardSlots.Length; i++)
        {
            if (cardSlots[i].isEmpty) continue; // 빈 슬롯이라면 건너뛰기

            float slotCardX = cardSlots[i].slotCard.transform.position.x;

            if (draggingCardX < slotCardX && i < cardSlots.Length - 1)
            {
                if (cardSlots[i + 1].isEmpty)
                {
                    DraggableUIObject card = cardSlots[i].slotCard;
                    card.transform.SetParent(cardSlots[i + 1].transform);
                    card.SetLocalPosZero();
                    break;
                }
            }

            else if (draggingCardX > slotCardX && i > 0)
            {
                if (cardSlots[i - 1].isEmpty)
                {
                    DraggableUIObject card = cardSlots[i].slotCard;
                    card.transform.SetParent(cardSlots[i - 1].transform);
                    card.SetLocalPosZero();
                    break; 
                }
            }
        }
    }

이러면 자연스럽게 카드와 가장 가까운 슬롯은 비어있는 상태가 된다. 이제 OnEndDrag에서 비어있는 슬롯으로 카드의 부모를 설정해주면,

    private void OnEndDragCard(DraggableUIObject drag)
    {
    	for(int i = 0; i < cardSlots.Length; i++)
        {
            if(cardSlots[i].isEmpty)
            {
                drag.transform.SetParent(cardSlots[i].transform);
                break;
            }
        } // ToDo; for문으로 비어있는 슬롯을 찾는것보다 더 나은 방법이 있을 수도 있음.
    	drag.SetLocalPosZero();
    }

기본적인 느낌을 흉내내볼 수 있었다.

profile
여기 글은 보통 틀린 경우가 많음

0개의 댓글

관련 채용 정보