내일배움캠프/TIL

내일배움캠프 3일차 TIL - 카드게임 제작

서보훈 2024. 9. 11. 20:56

오늘은 금요일까지 제출하는 미니프로젝트, 카드 맞추기 게임을 제작하는데 대부분의 시간을 투자하여 추가로 배웠다던가 하는점이 딱히 없기 때문에 구현 기능중 하나인 게임시작시 카드배치를 어떻게 했는가에 대해 적어보겠습니다.

 

private IEnumerator CardMove(GameObject moveObject, Vector3 targetPosition, GameObject[] fakeCards, int lastCard)
{
    //강제 update 구현...
    while (true)
    {
        //지정위치에 가까워지면 코루틴 강제 종료
        if (Vector3.SqrMagnitude(targetPosition - moveObject.transform.position) < 0.01f)
        {
            //마지막 카드의 이동이 끝나면 작동
            if(lastCard == cardNum - 1)
            {
                //가짜 카드들을 진짜 카드로 교체
                for (int n = 0; n < cardNum; n++)
                {
                    realCards[n].gameObject.SetActive(true);
                    Destroy(fakeCards[n].gameObject);
                }

                //게임 시작
                GameManager.Instance.isStart = true;
                //시작시 SFX 재생
                GameManager.Instance.PlayStartSound();
            }
            //코루틴 종료 전, 최종적으로 위치를 맞춰줌
            moveObject.transform.position = targetPosition;
            break;
        }
        //가짜 카드들 이동
        moveObject.transform.position = Vector3.Lerp(moveObject.transform.position, targetPosition, moveSpeed * Time.deltaTime);
        //강제 업데이트 구현...
        yield return new WaitForSeconds(Time.deltaTime);
    }
}

 

특이한점이 있다면, 움직임을 구현하기 위해 코루틴문을 사용하였다는점인데, 이 코루틴 함수를 사용하는 위치를 보면

 

//카드 생성 연출
private void CardArrangeEffect()
{
    //카드배치의 세로줄 수, 나머지가 있으면 +1 추가
    int lineNum = (cardNum % 4 == 0) ? cardNum / 4 : cardNum / 4 + 1;
    //가짜 카드 배열 생성
    GameObject[] fakeCardDeck = new GameObject[cardNum];
    //위치에 필요한만큼 가짜카드 생성
    for(int i = 0; i < cardNum; i++)
    {
        fakeCardDeck[i] = Instantiate(card, cardDeckPosition.transform.localPosition, Quaternion.identity);
        //가짜카드을의 버튼기능 비활성화
        fakeCardDeck[i].GetComponentInChildren<Button>().enabled = false;
    }

    //세로줄로 카드 이동
    for (int j = 0; j < lineNum; j++)
    {
        //가로줄로 카드 이동
        for (int k = 0; k < 4; k++)
        {
            //홀수일때, 중앙값이 -1인 알고리즘 필요 짝수일때, 중앙의 양쪽값이 -0.3, -0.7
            float middleNum = lineNum % 2 == 0 ? lineNum / 2f - 0.5f : lineNum / 2;
            //카드 목표지점
            Vector3 targetPosition = new Vector3(-2.1f + (1.4f * k), -1 + (middleNum - j) * 1.4f, 0);
            //카드 이동 코루틴
            StartCoroutine(CardMove(fakeCardDeck[j * 4 + k], targetPosition, fakeCardDeck, j * 4 + k));
        }
    }
}

 

이중 for문 내부에 카드이동을 구현한것을 볼 수 있습니다.

 

카드 배치를 Layout Group 을 사용하여 했기 때문에, 각 카드가 배치될 위치를 따로 지정해줄 필요가 있었으며 목적지까지의 이동을 Vector3.Lerp 로 구현하였는데 for문을 사용하여 update를 사용할 수 없었기 때문에 코루틴함수를 사용하여 Update와 같은 시간으로 동작하는 반복구조를 만들어 카드이동을 해결하였습니다.

카드의 이동이 완료되면 break를 사용해 while 문을 빠져나가 코루틴 함수를 종료하게 됩니다.

 

또한 이동할 가짜 카드, 목적지 뿐만 아니라 마지막 카드의 이동이 끝나면 가짜카드를 진짜 카드로 바꿔주면서 최적화를 위해 가짜카드들을 지워줄 필요가 있었기때문에 코루틴 함수의 매개변수가 4개 (이동할 카드, 도착위치, 가짜카드 배열, 이번 카드가 몇번째 카드인지) 가 되었습니다.