나 개발자 진짜 되냐?

모바일 게임 만들어보기 1 - 4 소나기 맞기 게임 본문

유니티를 공부해봐요!

모바일 게임 만들어보기 1 - 4 소나기 맞기 게임

Snow Rabbit 2024. 9. 12. 17:45

 

지난 시간까지!

 

1. 캐릭터를 움직였고

2. 물방울을 만들고 랜덤으로 떨어지게 했다.

 

자! 이제

3. 물방울을 반복적으로 만들어내줘야 한다.

게임의 전반적인 진행을 적는 로직은

게임매니저에서 관리해 주는 것이 원칙!

 

 

게임매니저를 만들어 보자!

 

Hierarchy > Create Empty

 

스크립트도 만들자!

 

Project > Assets > Scripts > Create > C#

 

이름을 정해주고 바로 옆에 빨간 아이콘을

음.. 약간 전반적인 게임내용을 담고 있기 때문에 아무거나 바꾸어두면

눈에 보기 편하다!

 

다음에 이 스크립트를

오브젝트에 담아준다.

 

그다음에

반복적인 행동을 해주기 위해

필요한 준비작업이 또 있다.

 

우리는 지금까지 Rain에다가

무한정 반죽을 준비해 두었다.

 

그러면 우리는 똑같이 찍어내기 위한 틀이 필요하다!

Prefabs

작업을 해주어야 한다.

 

Project > Assets > Create > Folder

이름은 Prefabs라고 해둔다.

 

그다음에

Hierarchy > Rain을 

Prefabs에 드래그해서 끌어 넣어준다.

 

 

그럼 이렇게 된다.

 

 왼쪽에 Rain이 하늘색이 됐는데

이 뜻은 Prefabs 되고 있다는 뜻을 나타낸다.

 

그렇게 해주면 Prefabs > Rain을 왼쪽에 아무리 끌어놔도

Prefabs의 Rain은 사라지지 않고 왼쪽에는

무한정으로 만들어 낼 수 있다.

 

자 시작화면에는 아무것도 없어야 하니

이제 맨 왼쪽에 Rain은 지워주도록 하자!

 

 

 

자!

이제 우리는 

게임매니저에게

 

Prefabs가 하는 일을 반복적으로 하게끔 하면 된다.

무한한 반죽과 틀이 준비되어 있으니

게임매니저는 이것을 동작하게만 해주면 된다.

 

게임매니저 스크립트 창을 켜서 

 

Prefabs는 gameObject이기 때문에

class 밑에

public GameObject rain;

을 생성해 준다.

 

이렇게 해주면

오른쪽에 GameManager ( Script )에

Rain이라는 친구가 생겼다.

 

우리는 여기 none를 하늘색 Rain으로 바꿔주어야 한다.

 

Prefabs에 있는 Rain을 

끌어다 두면 된다 ㅎㅅㅎ

 

자 이제 틀과 반죽이 준비되었으니

 

우리는 매니저를 통해 찍어내는 코드를 작성해 보자.

 

1. 반복적으로

2. 생성한다.

 

먼저 생성하는 코드부터 써보자

 

 

일단 함수를 하나 만들어주어야 한다.

Instantiate라는 친구는

 

우리는 이 Rain을 하나 만들 것이다!라는 뜻을 가진다.

 

전 시간에 우리가 Rain을 만들어서 파괴하는 것까지 했는데

 

Instantiate로 하나 만들고

Destroy로 파괴하고

 

이제 앞뒤가 맞네요!!

 

자 생성하기 함수를 만들어주었으니 해주었으니

Start에 가서 선언해주어야 한다.

 

함수 이름을 고대로 가져오면 된다.

 

Start 안에

MakeRain();해주면 끝!

 

호호!

우리는 2. 생성하기를 해주었으니 

이제 1. 반복적이게 를 해주어야겠지요?

 

반복적이게 라는 뜻을 가진 함수가 이미 준비되어 있습니다.

그 친구 이름은

 

InvokeRepeating();입니다.

이 친구 안에는 3가지 값이 들어간다.

 

1. 함수의 이름 넣어!

우리는 빗방울 생성 함수 이름을

MakeRain으로 방금 만들었다!

 

값을 넣을 땐

" " 큰따옴표로 안에 써주면 된다.

 

2. 몇 초 이후에 생성할래?

시작하고 나서 몇 초부터 할 거야?라는 뜻

 

우리는 바로바로 생성할 거야 0f

뭐 3초 뒤에 할 거야 3f 등등

 

3. 얼마나 자주 생성할래?

1초에 한 번씩 주기를 돌리자 1f

5초에 한번씩 돌리자 5f 등등

 

으로 설정해 주면

 

 

하늘에서 물방울이 떨어지게 된다.

 

지금까지 한 코드! 정리!

public class GameManager : MonoBehaviour
{
    //Prefabs는 일종의 GameObject이기 때문에
    public GameObject rain;

    // Start is called before the first frame update
    void Start()
    {
        InvokeRepeating("MakeRain", 0f, 1f);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    // 함수란, 반복적으로 실행되는 로직을 하나로 묶어놓은 단위
    // 우리는 이 작업을 반복적으로 수행할 것이기 때문에 함수를 만들어 놓는다.
    void MakeRain()
    {
        //( 게임오브젝트를) 생성하는 함수
        Instantiate(rain);
    }

}

 

 

자! 물방울에 이어서

이제 이 물방울을 내가 획득하면

점수를 획득할 수 있게 해야 한다.

 

점수 UI부터 만들어보자

 

아! 유니티에서 UI는 

카메라 시점이 아닌, 카메라 위치가 아닌

화면에 바로 띄워지는 것이다.

그래픽적인 요소라고 생각해 주면 좋다.

 

먼저! 폰트를 하나 저장해 준다.

 

사실 빙그레 폰트를 사용하고 싶었지만..

깔끔함을 위해

배달의민족 한나체를 사용했다.

누구나 다운로드가 가능하니

걱정 말고 검색해서 다운로드하자!

 

받고 난 후 

Assets에서

폰트 폴더를 하나 생성 후 그 안에 드래그해서 넣어주면 된다

 

이렇게 되면 성공 ✔

 

이제 점수판 UI를 만들어보자

 

 

Hierarchy 우클릭 > UI > Legacy > Text이다.

 

이렇게 해주면

 

오른쪽 화면에 이렇게 뜬다.

 

그리고 Hierarchy창에 새로운 친구

 

Canvas가 생겨져 있다.

이 친구는 바로 화면 앞에 띄워지는,

카메라 시점과 상관없는 친구가 된다.

 

자 이제 택스트를 꾸며보자

 

사진을 보며 따라 해봅시다!

 

먼저 Transform!

Rect가 앞에 붙었네요!

x, y 값 넓이 높이까지 설정해 준다.

밑으로 와서 폰트는 오른쪽 동그라미를 누르면

아까 우리가 다운로드하였던 폰트가 등장!!

 

밑으로 와서

Paragraph을 보면

정렬이 있다. 깔끔하게 가운데 정렬!!!!

 

그리고 밑에 색상은 흰색으로 설정했다.

좋아하는 색으로 바꾸어 보자!

 

자 이렇게 설정하면

지금 화면에서는 현재점수가 나오지만

main camera에서는

 

글씨가 적히지 않는 모습이 있다.

 

 

자 그러면 이제 우리는 4개의 텍스트를 만들어주어야 한다.

이름을 설정해 주고!

위에처럼

위치와 폰트를 맞춰주어 보자

 

Y는 건드리지 않고! X만 만지작해보자

 

ScoreLable 

X : -250

 

Score

X : -100

Text : 0

Font Size : 70 

 

TimeLable

X : 50

Text : 남은 시간

Font Size : 40

 

Time

X : 250

Text : 30.00

Font Size : 70 

 

이렇게 해주면!

 

 

예쁜 UI완성!

 

자 이제 이 친구를 작동시키려면?!

 

GameManager에게 가야 한다!

 

바로 스크립트로 이동!!

 

먼저!

GameManager에서 작동하게 하려면

꼭 필요한 함수를 써주어야 한다.

 

    //나 하나밖에 없다!! 그래서 여러 친구들이 나를 접근해줘야한다! 라는 의미의 함수 작성
    public static GameManager instance;

    private void Awake()
    {
        instance = this;
    }

 

 

 

이 친구이다.

 

변수를 선언해 주고

Awake는

Start 전에 호출되는 친구이다.

그래서 Start 전에

나는 나 자신이다. 나 하나다라고 써준 것이다.

 

자 선언해 주었으면

우리는 점수가 올라가기 위한 함수를 짜보자!

 

매개변수라.. 굉장히 어려운 친구가 등장했다.

주석을 한번 읽어보자

 

 

add 해주면 total도 있어야 하겠죠??

 

class 밑에 total 변수 선언!

 

int tntalScore;

 

다음에 저 AddScore 함수 안에

totalScore += score; 해주면

스코어의 점수가 토털스코어 쪽으로 더해져서 들어가게 된다.

 

자 이제 점수가 더해지는 코드는 짰고

 

이제 캐릭터가 물방울을 먹어주어야 한다.

 

하지만 우리는 저번에 캐릭터가 물방울과 충돌하는 코드는 짜지 않았었다!

 

복습하는 차원에서 해보자!!

 

기억을 떠올려보면

일단 부딪히는 곳에 충돌을 넣어줬었고,

땅의 태그를 변경

collision함수를 사용해서 충돌

그리고 destroy를 통해 파괴

 

이 정도 했던 거 같다.

 

그럼 먼저!

캐릭터에게 충돌을 심어주자

Hierarchy > Rtan에서

 

Add Componet

box Collider 2D를 설정한다.

 

엇 근데 너무 큰 거 아닌가? 싶다

 

그래서 바로 첫 번째 줄에

Edit Collider 버튼을 클릭해 준다.

해주고 나서 

다시 Hier > Rtan을 더블클릭해 주면!

 

연두색 네모칸이 나오는데

이곳이 충돌칸이다.

 

크기를 캐릭터보다 작게 해 준다.

 

요롷게!

 

캐릭터의 태그를 정해주어야 한다.

 

Hierarchy > Rtan에 가서 태그를 이번에는 만들지 말고 player를 눌러보자

설정까지 다 해주었다면

 

 

충돌 및 파괴를 해보자

 

 

주석에서 읽었다시피

public으로 선언해 주어야지만 외부에서 가져와서 사용이 가능하다.

 

우리가 아까 static으로 만들어 둔 intstance를 사용한 모습이다.

 

이렇게 해주었으니

 

이제 우리는 점수를 점수판에 띄워야 하는데 문제가 있다.

 

아까 점수를 0으로 설정해 둔 곳은 

Text이고

우리는 get으로 이 text를 가져와야 한다.

 

근데 이 친구는 Hier > score고

 

게임이 실행되고 있는 곳은 

 

Hier > GameManager이다.

 

즉, get은 같은 옵젝 안에 있는

Inspector만 가져올 수 있는데

오브젝트가 달라서 get으로 가져오는 게 어렵다는 뜻이다!

 

이럴 경우

GameManager에서 type이라는 친구를 선언해 준 후

그 type을 통해

score에서 text를 담아와야 한다.

 

자,

코드를 보자!

GameManager이다.

 

먼저, UI를 가져오기 위해서는

맨 위에

패키지를 가져와야 한다.

using Unity Engine.UI;

를 써준다.

 

다음에

내려와서 class 밑에

public  Text   totalScoreTxt;라고

 

써준다.

 

다음에 우리는

Score에서 Text Component에 Text에 넣어줄 거기 때문에

 

AddScore 함수로 가서

 

한 줄 추가해 준다.

 

totalScoreTxt.text = totalScore.ToString();

 

해석은 늘 뒤에서부터 하는 것이 좋다.

totalScore의 값

= 넣어준다.

 

totalScoreTxt 안에 text에 

라는 뜻이다.

 

ToString();

잘 보면 우리는 totalScore는 점수라서 int로 넣어주었다.

 

하지만 Text에 넣어야 하기 때문에

자료형을 맞춰줘야 하기 때문에

문자열로 맞춰줘!라는 뜻인 To.String라고 써주어야 한다.

 

 

문자열로 바꾼 totalScore의 값을

totalScoreTxt 안에 text에 넣어라.라는 뜻이다!

 

Uinty로 돌아와서

 

 

우리는 방금 GameManager에 

totalScoreTxt를 만들어줬었다.

그 변수가 지금 공백이기 때문에 채워줘야 한다.

 

누구로?

Score!!

 

이렇게 해주면

저 Score Object에 들어있는 Text Component를 가져오게 되는 것이다.

변수를 Text타입으로 만들었기 때문에 텍스트를 잘 가져온다!

 

 

여기까지 성공하셨다면! 고수..

 

 

이제

시간이 가게 하기

게임종료 화면

재시작 

정도만 만들어주면 될 것 같다.

 

자 먼저 UI부터!

아까 우리가 UI는 Canvas에서 나온다고 했으니

Canvas에서 우클릭해서 UI > Image를 해준다.

 

이 이미지는 

넓이 400

높이 250

로 해주고

 

색상은

232 / 52 / 78로 해준다.

 

자! 우리는 네모 칸을 만들었다.

이 칸 안에 게임 끝이 나와야 하기 때문에 Text가 있어줘야 한다

그래서 Image에서 우클릭

 

UI > Legacy > Text를 해준다.

 

Text는 이미지의 크기와 똑같게 유지해야 한다.

그래서

 

사이즈를 조절해야 하는데..

 

 

왼쪽에 과녁 같은 그림을 눌러주면 

여러그림이 나오는데 여기서

Alt Shift를 눌러준 상태에서

오른쪽 맨 끝에 있는 상하좌우에 화살표 만땅인 친구를 눌러준다!

 

그렇게 하면 이미지 사이즈에 Text가 맞춰지게 된다.

 

다음에 Text 글자크기는 80

폰트도 바꿔주고

가운데 정렬을 해준다.

 

색상도 255 255 255

로 맞춰준다.

 

그다음에 

끝! 리트?!

라는 글자를 적어주면 된다!

 

 

자라라!

 

이 문구는

마지막에 시간이 0이 될 때 나와야 하니까 잠시 비활성화시켜두자!

 

일단 이 이미지 이름을 EndPanel로 변경하고

비활은 이름 바꾸는 바로 옆에 체크를 해제하면!

우리 눈에 안 보이게 된다.

 

이렇게 해준 다음에

 

GameManager에서 시간이 흐르게 만들고!

시간이 0이 되면!

저 EndPanel이 켜지도록 만들면 된다.

 

 

코드를 작성해 보자!

 

먼저 시간은 30초로 정하고 타이머기 때문에 점차 감소해서 0까지 가야 한다.

-=를 써주면 되지 않을까? 싶다.

 

먼저 전체시간값 변수를 만들어준다.

 

변수는 늘 말했지만!

class 바로 밑에 써준다!!!

 

float totalTime = 30.0f;

 

다음에 계속 숫자가 줄어들어야 하기 때문에

반복!

그래서 Update에 써주어야 한다.

 

어멋! 저 delta는 누구인가요?

주석에 적어놨지만

프레임은 좋은 성능일수록 더 빠르게 움직인다고 한다.

그렇기 때문에 1초라는 시간에 움직이는 게 기기마다 각각 달라서,

통일된 시간을 쓰는 것이 이 deltaTime이다.

 

자 이제 시간은 줄어드니

위에 했던 대로

이 시간을 Text로 가져와서 UI에 보여주어야 한다.

 

먼저,

변수를 하나 만들어줬었다.

 

Public Text timeTxt;

 

다음에 

 

timeTxt.text = totalTime.ToString("N2");

Text로 만든 timeTxt 컴포넌트 안에 있는 text에 넣어줄 건데,

totalTime

ToString 문자열로 바꿔서

 

"N2" 못 보던 건데

소수점 둘째 자리까지 보여주세요!라는 뜻

 

그다음 중간점검 실행!

 

실행할 때 꼭!!!

GameManager에 TimeTxt 에다가

드래그해서 텍스트를 넣어주어야 한다!!

 

❗❗잊지 않기❗❗

 

이제는

시간이 0초가 됐을 때, 아까 만든 판넬이 켜져야 한다.

 

그렇다면 지금까지 과정은

시간이 0이 되기 전까지 이까

조건문을 만들어서

0초가 되기 전엔

아까 적어놓은 코드가 실행되어야 하고,

 

0초가 되면

판넬이 켜지는 코드를 작성해 보자.

 

 

주석이 많아서 그렇지

쓴 문장은 단 두줄입니다.

 

if / else를 써서

0보다 클 때, 그리고 나머지로 분류한다.

 

그리고 나머지일 경우 ( else )

time을 0으로 설정,

timeScale이라는 친구도 활용해서 프레임도 0이 될 수 있게 맞춰주도록 하자

 

그리고 우리는 이 과정 전체가 다 UI에 보여 야하기 때문에

if문이 끝나는

마지막에 문자열로 바꿔서 넣어주는 작업을 한다.

 

 

자 0초가 되니깐 화면이 똵! 멈췄다.

프레임도 멈췄기 때문에

더 이상 물방울도 시간도 점수도 오르지 않는다.

 

캐릭터는 아마 계속 움직이고 있을 것이다. 

이 부분은 나중에 정리하자!

 

 

자 이제 endPanel이 나올 차례!!

 

판넬을 켜주려면

또 게임오브젝트를 가져와야 한다.

 

자 GameManager에서 함수 입력

 

public GameObject endPanel;

 

해주고 유니티 돌아오면

또 하나가 생겼죠!

여기에 endPanel을 드래그해서 드롭해 준다.

 

타임이 0이 됐을 때

판넬이 켜져야 하니까

else로 가면..

 

endPanel.SetActive(true);

 

움직이는 상태를 set 해준다.

참으로 바꿔준다.

 

로 해석 할 수 있다.

 

 

자, 이제

다시?라는 문구가 나왔으니

그 문구를 누르면 다시 시작되도록 만들어주어야 한다.

 

판넬을 눌렀을 때 작동해야하기 때문에 버튼 이라는 이름을 사용했다.

 

그리고 이것을 버튼으로 활용할 것이니..

 

endPanel에 들어가서 새로운 컴포넌트를 만든다.

 

이 친구는 Button..^^

 

 

요렇게 만들어주면 된다!

 

 

자 이제 우리는,

버튼을 눌렀을때

재시작을 해야 한다.

 

 

즉 끝나면

다시 처음부터 돌아가야 하기 때문에

MainScene이 다시 켜져야 한다.

 

이 점을 생각하며

재시작 스크립트를 짜보자

 

먼저 스크립트들 있는 곳에 하나 새로 만들고

 

그의 이름은 RetryButton이라고 하자.

 

안의 내용을 다 지우고

 

우리는 Main Scene를 불러와야 한다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class RetryButton : MonoBehaviour
{
   //게임을 다시 시작하는것은 MainScene를 다시 불러주면 된다!!
   //Scene를 불러오기 위해서는..패키지하나, 함수하나를 추기한다.

    public void Retry()
    {
        //Scene을 불러오기 위해서는 Scene Management (패키지) 에 있는
        //scene manager을 이용해야한다. scene를 가져올땐 get이 아니라 load라고 해야한다.
        SceneManager.LoadScene("MainScene"); 
    }
}

 

먼저 패키지를 하나 만든다.

using UnityEngine.SceneManagement;

 

scene과 관련된 패키지인듯하다.

이 패키지 덕에

밑에 보면 우리는 

 

SceneManager.LoadScene("MainScene");

이 친구를 사용할 수 있다.

 

패키지 덕분에

SceneManager을 쓸 수 있고 그 안에서

MainScene이라는 이름의 scene를 load 해줘라

 

 

자 그러면 이제 이 함수

Retry를 누가 불러줘야 한다.

 

버튼을 클릭했을 때 함수를 클릭해줘야 하기 때문에

 

Unity로 넘어가서 만져준다.

 

 

먼저

 

Retry를 부르려면

버튼을 눌러줘야지만 부를 수 있으니

EndPanel 안에

RetryButton 스크립트를 드래그 앤 드롭해서 넣어준다,.

 

다음에

 

Inspector에Button이 있다.

버튼에서 내려가보면

 

OnClick가 있다.

이 온클릭은

 

클릭이 되었을 때!! 뜻하며

클릭했을 때 다음동작을 표현할 수 있는 곳이다.

 

+버튼을 눌러서

추가할 수 있다.

 

지금은 None으로 되어있는데

버튼을 눌렀을 때니까

 

Endpanel 오브젝트를 

드래그 엔 드롭 해서 넣어줘야 하고,

 

해주면 No Function이

활성화가 된다.

 

여기 안에 있는 내용들은

Inspector 안에 있는 컴포넌트들이 들어 있다.

 

즉 이 버튼을 눌렀을 때

컴포넌트들은 어떤 동작을 하는가 를 뜻한다.

우리는 Retry라는 함수를 실행시키도록 한다.

 

 

자 여기까지 했으면,

실행해 보도록 하자!

 

 

잘되나요?

 

엇 이상하다고요?

 

다시 시작을 누르는데 시간도 안 가고 물방울도 안 떨어지네요..

 

그 이유는!

우리가 아까 

시간이 0이 됐을 때

timeScale을 0으로 설정해 놨기 때문

 

다시 게임을 시작하려면

게임시작에 맞춰

timeScale도 1이 되어야 한다!

 

GameManager 스크립트로 가서

 

Awake 밑에

*Awake는 start 전에 시작하는 함수라고 합니다 ^^

 

Time.timeScale = 1.0f; 로 초기화 시킨다.

 

그러면 정상적으로 작동한다!!!!! 

 

 

+ 추가 +

 

빨간색 물방울을 만들어보자!

이 빨간색 물방울은 점수가 -5점 깎인다.

 

물방울을 추가해서 만들어보자!

 int type = Random.Range(1, 5); // 총 4종류여서 파랑 대중소 / 빨강

 if (type == 1)
 {   
     size = 0.8f;
     score = 1;
     renderer.color = new Color(100/255f, 100/255f, 1f, 1f);
     //색은 f 값으로 들어가고 최댓값으로 나누어주어야한다.
     //유니티에서는 150을 하드코딩했지만, 여기서는 255로 나누어줘야한다.
 }
 else if (type == 2) // else if를 해주지 않고 다 따로따로 if문을 만들면 별개기 때문에 하나씩 다 검사하게 된다.
 {
     size = 1.0f;
     score = 2;
     renderer.color = new Color(130 / 255f, 130 / 255f, 1f, 1f);
 } 
 else if (type == 3) 
 {
     size = 1.2f;
     score = 3;
     renderer.color = new Color(150 / 255f, 150 / 255f, 1f, 1f);
 }
  else if (type == 4) //빨간 물방울
 {
     size = 0.8f; // 나쁜거라 가장 작게
     score = -5; // 점수가 떨어져야하니깐 음수!
     renderer.color = new Color(255 / 255f, 100 / 255f, 255 / 255f, 1f); // 빨간색이면 다좋아요!
 }

 

쨕쨖쨖!!

 

- 빗물 받는 르탄이 완 - 

 

 

< 이 프로젝트는 스파르타 코딩수업에서 배운 내용을 복습 한 내용입니다. >