원래 아직 배우는 단계니까 하나를 하더라도 천천히, 충분히 이해하면서 넘어가자 라는 마음에 나는 한 게임을 만드는 시간이 남들보다 좀 오래 걸렸는데,
이 게임의 경우 미니 프로젝트에 기초가 되는 부분이라 하루만에(사실 하루도 아니고 5~6시간..?) 정말 몇배 집중해서 머릿속에 넣느라 정신이 없엇던 게임이었다.
게임은 간단하다, 주어진 시간 안에 뒤집혀져있는 카드를 뒤집어서 한 쌍을 맞추는 게임이다.
한번에 두개를 뒤집을수 있으며 틀린 카드가 나오면 다시 뒤집히고, 같은 카드가 나오면 그 카드들은 사라진다.
전부 다 맞추면 클리어!
처음 시작하면 평소와 같이 MainScene을 구성해준다, 이번 게임은 MainScene 하나로 진행.
오브젝트는 크게 UI/텍스트(타이머, 게임오버), 보드(카드 구성해주는 오브젝트), 카드, 게임매니저 로 이루어져 있다.
Board
보드 오브젝트에서 카드를 깔아주기 위해 스크립트를 넣어주었다.
void Start()
{
//리스트
int[] arr = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 };
arr = arr.OrderBy(x => Random.Range(0f, 7f)).ToArray();
}
배열을 나열해준 후 랜덤하게 섞기 위한 코드를 작성해주었으며, using문에 Ststem.Linq를 추가해주었다.
- Linq : C#에서 제공해주는 데이터를 다루는 기능(라이브러리)
언어 확장 집합, 배열(Array), 리스트(List), 데이터베이스(DB)등을 검색, 정렬, 변환 하는 기능을 제공, 내가 원하는 데이터만 가져오고 싶은 경우 사용할 수 있는 기술 - OrderBy : Linq의 메서드, 정렬하기 위한 기능
- arr : 배열(array)
- int[] arr = { 0, 0, ~ 7, 7 }; : 0~7까지의 카드를 두개씩 정렬
arr로 숫자 리스트를 만든 다음, Random.Range를 통해 배열을 무작위로 섞어주었다. (숫자는 카드에 해당하며 0, 0은 같은 한쌍을 의미)
for (int i = 0; i < 16; i++)
{
//this = board : board 밑에 생성되게
GameObject go = Instantiate(card, this.transform);
//나머지값을 구하는것은 %, 몫은 /
float x = (i % 4) * 1.4f - 2.1f; // 나머지 * 카드간격 - 카드 위치
float y = (i / 4) * 1.4f - 3.0f; // 몫 * 카드간격 - 카드 위치
go.transform.position = new Vector2(x, y); // 카드배치
//카드 스크립트를 가져와서 카드에 번호를 넣어주기 위해 작성
go.GetComponent<Card>().Setting(arr[i]);
}
- int i = 0 : 정수 0 = i
- i < 16 : i가 16보다 작을 경우 중괄호 안의 로직을 계속 반복하여 실행
- i++ : 중괄호 안의 로직을 실행할때마다 i는 1씩 증가
반복하여 실행하다 보면 i가 16이 될텐데, 그때 이 로직의 반복문이 끝나게 된다.
for 안에는 카드를 생성하기 위해 Instantiate를 사용하였으며 카드 한장이 아닌 여러장을 배치해주기 위해 다른 로직을 추가해주었다.
- float x = (i % 카드장수) * (카드 크기+카드 간격/너비) - 첫번째 카드의 위치(transform)f;
- float y = (i / 카드장수) * (카드 크기+카드 간격/너비) - 첫번째 카드의 위치(transform)f;
나의 경우 각각 가로세로에 4장씩, 총 16장의 카드를 배치하고자 하며
카드의 크기가 1.3f, 간격은 0.1f로 설정해주기 위해 1.4f, 배치되는 카드의 위치를 맞춰주기 위해 trantsform의 position 값을 각각 설정해 주었다.
Card
카드는 오브젝트로 만든 후 프리팹화 시켜주었으며 앞면과 뒷면을 구분하기 위해 각각 Front, Back 이름으로 설정해주었다.
void OpenCard 메서드에 카드를 뒤집는 모션을 위한 애니메이션을 하나 추가해주었으며, SetActive로 front, back 의 활성화를 지정해주었다.
스크립트에서 해당 오브젝트들을 접근할 수 있도록 public으로 선언해주었다, 이 내용을 바탕으로 시작
각각의 카드에 랜덤으로 섞인 값을 넣어주기 위해 변수 추가( int idx = 0; )
* int idx = 0 ; : index의 약자인 idx를 입력, 초기값은 0으로 세팅,
public void Setting(int number)
{
idx = number;
frontImage.sprite = Resources.Load<Sprite>($"이미지명{idx}");
}
- Resources : 유니티 내장 클래스, Resources.Load<>()를 통해 Rescources 폴더 내의 에셋을 불러올 수 있음
- GameObject obj = Resources.Load<GameObject>("폴더, 이미지명 등");
- arr를 이용하여 0~7까지의 숫자로 정해주었기 때문에 idx에 들어갈 숫자도 0~7로 하여 이미지명을 설정해주었다.
코드로 작성해놓은 대로 하려면 이미지명0 이미지명1이 되어야 한다.
GameManager
Card의 firstCard와 SecondCard에 접근하기 위해 public 으로 선언해주었고, 카드들의 접근을 위해 싱글톤 처리를 해주었다.
public void Matched()
{
// 첫번째 카드와 두번째 카드가 일치한다면
if(firstCard.idx == secondCard.idx)
{
// 첫번째 카드와 두번째 카드는 파괴, 카운트 2 추가
firstCard.DestroyCard();
secondCard.DestroyCard();
cardCount -= 2;
// 카드 개수가 0이 되었을때
if(cardCount == 0)
{
// 즉시 게임을 끝내고 끝 텍스트 오브젝트를 바로 켜준다(SetActive)
Time.timeScale = 0.0f;
endTxt.SetActive(true);
}
}
else
{
// 일치하지 않을때엔 카드를 다시 닫아준다 (되돌려준다)
firstCard.CloseCard();
secondCard.CloseCard();
}
// 다음 카드를 선택할 수 있도록 초기화(null값 할당)
firstCard = null;
secondCard = null;
}
}
if(firstCard.idx == secondCard.idx) 를 통해 첫번째, 두번째 카드가 일치한지를 확인하고, 불일치할 경우 else로 넘어가게 된다.
추가로 미니 프로젝트에선 다른 조원분께서 높은 레벨의 난이도에서 3개의 카드를 1쌍으로 만드신 적이 있는데, 이런 경우엔 조건문을 아래와 같이 작성한다.
if (firstCard.idx == secondCard.idx && secondCard.idx == thirdCard.idx)
&&(and) 사용없이 나는 1==2==3 이런식으로만 생각했는데, 그럴 경우엔 1==2 : true/false 인 상태에서 3(정수)를 비교하는 것이 되어 오류가 발생할 수 있다고 한다.
하여 &&(and)를 사용하여 작성하면 첫번째, 두번째, 세번째 카드를 모두 선택한 후 비교 실행되며 세 카드가 일치/불일치 할 경우는 일반 난이도와 같다.
다만 나는 처음에 저 코드만 보고 두번째 카드까지 뒤집었을때 틀리면 돌아가는거 아냐? 라고 생각했는데 그렇게 하려면 !=를 사용하면 가능하다.
이렇게 4주차 카드 뒤집기 게임도 끝.
다만 급하게 무작정 만들기만 했을때엔 이게 뭐지 했지만 미니프로젝트 하면서 알게된 것들로 인해 글 작성하면서 어어 이거다 하는게 많기도 했고 나 좀 잘알고있네 싶어 조금 뿌듯햇따.
사실 1주일 앓아눕고 와서 많이 까먹어서 속상한것도 컷따..
'Unity > Unity Study' 카테고리의 다른 글
[Unity] localPosition 변경에 따른 움직임/이펙트 변화 (0) | 2025.02.18 |
---|---|
[Unity] '카드 뒤집기 게임' 의 기능 추가 (0) | 2025.02.05 |
[Unity] 세번째 게임, '고양이 밥주기 게임' 완성 (0) | 2025.01.28 |
[Unity] 1주차, 미니 프로젝트 진행 중 (0) | 2025.01.23 |
[Unity] 두번째 게임, '풍선을 지켜라' 마무리 (0) | 2025.01.06 |