나는 해야 한다. 그러므로 나는 할 수 있다.
1. 풍선을 지켜라 게임
싱글톤 구현 하기
public static GameManager Instance;
public void Awake()
{
if(Instance == null)
{
Instance = this;
}
}
싱글톤이란?
"너는 딱 하나야!" 라고 할 수 있게 세팅해 두는 것. 이렇게 세팅해 두어야 다른 스크립트에서 나를 참조할 수 있다.
어제의 글과 조금 구조가 달라졌는데
Instance == null 일 때, 즉 이 변수가 비어 있을 때 Instance = this를 해주겠다는 의미이다.
선생님께서 박스가 null null 하다.. 라고 외우라고 하신다.
최고 점수 구현하기
여기서 조금 생소한 표현이 나왔다. 데이터를 저장하고 불러오기 위해
PlayerPrefs.SetFloat("bestScore", 어떤숫자값);
PlayerPrefs.SetString("bestScore", 어떤문자열);
어떤숫자값 = PlayerPrefs.GetFloat("bestScore");
어떤문자열 = PlayerPrefs.GetString("bestScore");
Set, Get을 사용했는데 자주 사용하지 않았던 구문이라 생소하다.
데이터를 저장하기 위해 Set을 데이터를 불러오기 위해 Get을 사용하고
PlayerPrefs.HasKey("bestScore")
HasKey를 사용하여 데이터가 있는지를 확인한다. 데이터가 있으면 true, 없으면 false를 반환한다고 한다.
또한 데이터를 모두 지우기 위해
PlayerPrefs.DeleteAll();
Delete를 사용한다.
2. 고양이 밥주기 게임
충돌 판정 제어
이번 게임에서는 어려운 부분이 없다싶이 했지만, 그래도 헷갈리는 부분은 있었다.
이 게임에서는 내가 날리는 발사체가 밑으로 내려오는 적에게 충돌하는 형식으로 이루어져 있다.
충돌한 판정을 주기 위해 먼저
- 발사체에 tag를 넣어준다.
- 발사체에 Rigidbody2D, Collider를 달아 준다.
- BodyType을 Kinematic으로 잡아준다. 이것은 중력의 영향을 안받겠다는 의미이다. (내가 밑에서 위를 향해 쏘기 때문이다.)
- 그 뒤 IsTrigger에 체크한다. -> 중력의 영향을 안 받을 때에 이것을 체크해주면 된다.
- 적에게도 똑같이 collider를 달아 준다.
그 뒤 스크립트에 충돌을 구현한다.
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("Food"))
{
Debug.Log("맞았다!");
}
}
이번에는 OnTriggerEnter2D를 사용했다.
그 이유는 위에 중력을 안받기 위해 Kinematic을 사용했기 때문에 IsTrigger를 체크하여서이다.
3. 르탄이 카드 뒤집기 게임 만들기
카드 만들고 배치하기
사실상 이번 게임의 알파이자 오메가라고 생각한다.
카드를 까는건 많은 방법이 있겠지만 평소에 해오던 방법보다 튜터님께서 가르쳐주신 방법이 깔끔하고 좋은거 같다.
public Transform cards;
public GameObject card;
void Start()
{
for (int i = 0; i < 16; i++)
{
GameObject go = Instantiate(card, this.transform);
}
}
일단 반복문을 사용하여 GameObject를 16장을 만든다. ( 4x4 카드게임을 만들기 때문 )
다음으로 카드를 나뉘게 하는 로직을 사용하게 된다.
| [예를 들어 1번째라고 하면] → x : 1을 4로 나눈 나머지 = 1 → y : 1을 4로 나눈 몫 = 0 ⇒ (1,0) 위치 ⇒ (1.4씩 곱해주면) ⇒ (1.4, 0) 위치 [예를 들어 7번째라고 하면] → x : 7을 4로 나눈 나머지 = 3 → y : 7을 4로 나눈 몫 = 1 ⇒ (3,1) 위치 ⇒ (1.4씩 곱해주면) ⇒ (4.2, 1.4) 위치 |
위의 방식을 사용하여 카드의 좌표를 설정하게 된다.
중간 중간 나오는 1.4의 의미는

실제로 이런 크기를 가지기 때문이다.
위의 로직을 코드로 옮겨보면
float x = (i % 4) * 1.4f;
float y = (i / 4) * 1.4f;
go.transform.position = new Vector2(x, y);
이런식인데 %는 나머지 연산자, / 는 나누기 연산자이다. 그 뒤 transform.position으로 Vector2의 좌표에 넣고 이동시켜준다.
위의 마지막 줄 코드는 정말 많이 사용하는 거 같다. 반복해서 정리해도 모자랄 거 같아 한 번 더 복습 겸 설명을 적어주었다.
이제 카드는 옮겼지만 카드를 섞어주지 않아 카드 게임의 의미는 아직 없다.
카드를 섞어주기 위해
using System.Linq;
...
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();
arr이라는 1차원 배열에 짝을 맞춘 16개를 선언해 주고
OrderBy = 시퀀스를 오름사춘으로 정리한다는 의미. ( 내림차순은 OrderByDescending 이라고한다.)
Random.Range(0f, 7f) = 0 이상 7미만의 float 값을 랜덤하게 만들어 주고
ToArray() = 생성된 난수를 각각 arr[0], arr[1], arr[2] ... 에 부여 해주는 의미이다.
이렇게 되면 각 배열에는 랜덤한 키 값이 할당되고 그 키 값에 따라 배열이 랜덤하게 섞이게 되는 것이다.
이제 카드의 위치를 옮기고 랜덤하게 섞는 것 까지 구현이 됐다.
이 뒤로는 카드를 뒤집어서 같은 카드면 삭제, 아니면 다시 뒤집어지는 카드 게임의 형태로 흘러갔다.
실제로도 쉽다고 생각하며 진도가 쭉쭉 나갔다. (분명 쉬웠는데..)
Invoke vs Coroutine
강의를 쭉 듣가다 튜터께서 Invoke를 사용하시는 걸 봤다.
나는 사실 주먹구구식으로 코딩을 많이 했기 때문에 신경 쓰이지 않았었다.
근데 왜 적냐? 그건 바로! 오늘 다른 조 분들 발표 때 코루틴 얘기가 상당히 많이 나와
코루틴을 사용하는 법을 복습할 겸 코루틴으로 코드를 바꿔보자! 했기 때문이다.
public void DestroyCard()
{
Invoke("DestoryCardInvoke", 0.5f);
}
void DestoryCardInvoke()
{
Destroy(gameObject);
}
public void CloseCard()
{
Invoke("CloseCardInvoke", 0.5f);
}
void CloseCardInvoke()
{
anim.SetBool("isOepn", false);
front.SetActive(false);
back.SetActive(true);
}
위의 코드를
public void DestoryCard()
{
StartCoroutine(DestroyCardCO());
}
IEnumerator DestroyCardCO()
{
yield return new WaitForSeconds(1f);
Destroy(gameObject);
}
public void CloseCard()
{
StartCoroutine(CloseCardCo());
}
IEnumerator CloseCardCo()
{
yield return new WaitForSeconds(1f);
anim.SetBool("isOpen", false);
Front.SetActive(false);
Back.SetActive(true);
}
바로 이렇게 코루틴 형식으로 바꿔 보았다. 잘 썻는지는 모르겠지만 일단 잘 돌아가기도 한다!
그렇게 게임은 완성되었다.
게임을 완성 시키고 머리 식힐 틈 도 없이 위에 말한 발표에 갔다.
선행 캠프를 들었던 사람들은 위의 게임으로 팀 프로젝트를 했다고 하다.
그래서 나도 시간이 남는 겸 게임을 발전 시켜 보기로 했다. (이 때 까진 쉽게 할 줄 알았습니다 하하..)
한 5가지 정도 기능을 추가 해보려고 했다.
- 가장 먼저 ESC 메뉴, 메뉴를 통해 사운드 관리, 게임 정지, 게임 재시작 등의 단순한 기능
- 현재 구현으로는 카드 2개를 누르고 카드를 더 누르면 3~4장 까지도 앞면으로 바뀐다. 이것을 방지하기 위한 대책
- 처음에 한 번 전체적인 앞면을 1초 정도? 한 0.1초 간격으로 촤라락 넘어가면서 보여주기
- 가장 마지막에 맞춰야 하는 카드, 맞추면 전체로 한번 섞이는 등의 특별한 효과가 있는 카드 구현 ( 강조 효과도 물론 구현)
- 한 장을 앞면으로 해놓고 오래 못찾고 있으면 정답 카드를 반짝여서 힌트를 주는 기능
이렇게 간단한 5가지 정도를 구현 해,,보,,고 싶었다.. 금방 할 줄 알았지...
결론만 말하자면 2번까지 밖에 아직 구현 못했다. 주말동안 빡세게 구현해봐야겠다.
이렇게 까지 오래 걸릴 줄은 몰랐자나~
4. 회고
오늘은 늦게 합류한 만큼 첫 주차 강의를 다 몰아보고 발표 듣고, TIL 특별 강의까지 들으니 시간이 정말 후딱 지나갔다.
발표를 들으면서 든 생각은 "와 다들 잘하고 열심히 하는구나." 였다. 나도 빨리 합류해서 사전캠프를 들었으면
좋았을 것 같다는 생각과 함께 나도 혼자서 뭐라도 사부작 사부작 해보자 라는 마음에 저녁 먹고는 유니티만 뚜드리고
있었던 것 같다. 이제 이틀 차인데 조바심이 나는구만. 안 뒤쳐지게 열심히 해야겠다. 라는 생각에 잠기는 똑같은 하루 였다.
'내일배움캠프 - TIL > 내일배움캠프 - TIL' 카테고리의 다른 글
| 내일배움캠프 6일차 TextRPG (5) | 2025.04.17 |
|---|---|
| 내일배움캠프 5일차 TIL 2주차 강의 5 (0) | 2025.04.16 |
| 내일배움캠프 4일차 TIL 2주차 강의 4~ (0) | 2025.04.15 |
| 내일배움캠프 3일차 TIL 2주차 강의 1~4 (0) | 2025.04.14 |
| 내일배움캠프 1일차 TIL 빗물받는 르탄이, 게임 속 상호작용 분석 컨텐츠 (1) | 2025.04.10 |