김김김의 게임개발
  • Unity 게임 개발 #8 - 카드 매칭 게임<Teammate-Cardgame> 4
    2023년 08월 09일 20시 58분 46초에 업로드 된 글입니다.
    작성자: noun06

    유니티를 사용하여 개발한 카드 맞추기 게임입니다. 팀 미니 프로젝트로 진행하였습니다.


    1. 카드 배열 늘리기

    • 기존 카드 프리팹을 활용하기 위해 가로 행은 4로 고정한다를 전제로 배열 늘리기를 진행함. (4x3, 4x4, 4x5)
    • public 인수형 변수로 행과 열을 선언하고 "행 x 열 = 카드 총 개수"를 나타내는 cardCount 변수 선언.
    • 그리고 cardCount를 기준으로 bfour[ ] 배열에 반복문을 통해 할당.
    • 배열의 위치 잡기의 경우 기존 1.4f 스페이싱을 기준으로 y 위치만 조정해서 4x3, 4x4, 4x5 모든 경우에 정확하게 위치하게 세팅.
     //gameManager.cs
     
     public int rows = 4; // 행
     public int cols = 4; // 열
     
      void Start()
        {
            Time.timeScale = 1.0f;
    
            int cardCount = rows * cols; // 카드 총 개수
            int[] bfour = new int[cardCount]; 
    
            for (int i = 0; i < cardCount; i++)
            {
                bfour[i] = i / 2; // 0부터 (cardCount / 2 - 1)까지 반복되는 값 할당, 4x4일 때 {0,0,1,1 ... 7,7}
            }
    
            bfour = bfour.OrderBy(item => Random.Range(-1.0f, 1.0f)).ToArray();
    
            for (int i = 0; i < cardCount; i++)
            {
                GameObject newCard = Instantiate(card);
                newCard.transform.parent = GameObject.Find("Cards").transform;
    
                float x = (i / cols) * 1.4f - 2.1f;
                float y = (i % cols) * 1.4f - (cols - 1.0f);
                newCard.transform.position = new Vector3(x, y, 0);
    
                string bfourName = "bfour" + bfour[i].ToString();
                newCard.transform.Find("front").GetComponent<SpriteRenderer>().sprite = Resources.Load<Sprite>(bfourName);
            }

     

    • 그리고 4x5 에서 필요한 카드가 20장이므로 imageName 배열에도 새로 2 종류의 이미지를 추가함. 
     //gameManager.cs
     
     public void isMatched()
        {
           ..//
            if (firstCardImage == secondCardImage)
            {
                ..//
    
                string[] imageName = new string[] { "이홍준", "이홍준", "이홍준", "김나운", "김나운", "김나운", "진재환", "진재환", "르탄이", "르탄이" };
    
                for (int i = 0; i < 10; i++)
                {
                    if (firstCardImage.Equals("bfour" + i)) // firstCardImage 값이 bfour0 ~ bfour9 중 어떤 것인지 확인
                    {
                        successTxt.GetComponent<Text>().text = "성공! 팀원 " + imageName[i] + "입니다."; // i값 그대로 위에 배열에서 불러옴
                    }
                }
                ..//
            }

     

    2. 카드 배열 별 스테이지 시스템

    • 스테이지 선택과 현재 해금한 스테이지가 구분 가능한 시작 화면 제작.
    • 각 배열마다의 씬을 새로 생성. 스테이지를 선택할 수 있는 씬도 하나 생성.(각 스테이지 별로 총 3개 버튼)
    • LevelSelection.cs은 레벨 선택 씬에서 사용, 3개의 스테이지 이동 버튼을 하나의 배열로 만들어서 할당.
    • levelAt이라는 플레이어의 최대 진행 레벨을 나타내는 정수형 변수 선언.
    • 유니티 Build Settings에 들어있는 씬 기준으로 1부터5까지 사용되고, 디폴트는 현재 씬인 2로 할당.
    • levelBtns[ ]배열에서 특정 인덱스의 번호를 넣었을 때 levelAt 값보다 큰 인덱스의 버튼은 비활성화.
    • 현재는 levelAt이 2이므로 첫번째 배열인 "스테이지 1로 이동하기" 버튼만 활성화된 상태.
    //LevelSelection.cs
    
    public class LevelSelection : MonoBehaviour
    {
        public Button[] levelBtns; //인스펙터의 레벨 버튼 할당
    
        private void Start()
        {
            int levelAt = PlayerPrefs.GetInt("levelAt", 2); 
            //levelAt : 플레이어의 최대 진행 레벨(현재 'LevelSelect' 씬의 값은 2)
    
            for (int i = 0; i < levelBtns.Length; i++)
            {
                if(i + 2 > levelAt) // levelAt 값보다 높은 인덱스에 해당하는 버튼 비활성화(levelBtns[1],levelBtns[2])
                {
                    levelBtns[i].interactable = false;
                }
            }
        }
    }

     

    • MoveToNextLevel.cs은 각 스테이지 씬의 플레이 종료 후 나타나는 "다음으로" 버튼에 사용.
    • 현재 씬의 다음 씬을 나타내는 nextSceneLoad 변수 선언. (스테이지1 씬의 경우 2+1 → 3)
    • nextSceneLoad 변수를 로드하는 NextScene()함수를 만들어서 각 버튼에 넣음.
    • NextScene() 내 진행상황을 저장하기 위해 levelAt 값을 업데이트.(스테이지1에서 버튼 누를 경우 2에서 3으로 업데이트되고 스테이지2도 자동 해금.)
    • 업데이트된 데이터는 PlayerPrefs에 저장되어 게임을 종료해도 진행상황 저장.
    //MoveToNextLevel.cs
    
    public class MoveToNextLevel : MonoBehaviour
    {
        public int nextSceneLoad;
    
        private void Start()
        {
            nextSceneLoad = SceneManager.GetActiveScene().buildIndex + 1; //현재씬의 다음씬
    
        }
    
        public void NextScene() //endCanvas의 "다음으로" 버튼 눌렀을 때 호출
        {
           
            SceneManager.LoadScene(nextSceneLoad);
    
            if(nextSceneLoad > PlayerPrefs.GetInt("levelAt")) //진행상황 저장을 위해 levelAt 값 업데이트
            {
                PlayerPrefs.SetInt("levelAt", nextSceneLoad);
            }
    
        }
    }

     

    3. 사용자 데이터 초기화

    • 게임 시작화면의 옵션창에 "데이터 초기화"라는 버튼제작.
    • 지금까지 저장되었던 levelAt 업데이트 내용이나 팀원 분이 만든 최고 점수 저장 값들을 전부 삭제시킴.(스테이지 잠김)
    //DeletePlayerPrefs
    
    public class DeletePlayerPrefs : MonoBehaviour
    {
        public void ResetData() //Player 데이터 삭제
        {
            PlayerPrefs.DeleteAll();
        }
    }

     

    4. 결과물

     

     

    댓글