티스토리 뷰

반응형

계속해서 Flappy Bird 를 만들어보겠습니당~

이전 포스트를 안보셨다면 참고해주세요!😄

GitHub 코드, 파일, 실행영상은 글 마지막에 있습니다.

 

 

2020/03/12 - [Unity 게임 개발] - [Unity 게임 개발 고수 되기 #1. Flappy Bird ] 03. 게임오버 UI, PlayerPrefs를 이용한 데이터 저장, 랭킹 UI 구현하기

 

[Unity 게임 개발 고수 되기 #1. Flappy Bird ] 03. 게임오버 UI, PlayerPrefs를 이용한 데이터 저장, 랭킹 UI 구현하기

오늘도 저번 포스트에 이어서 Flappy Bird 게임을 만들어보겠습니다! 많은 의견 주세용😁~ 앞 포스트를 못보셨으면 링크 참고해주세요! 2020/03/11 - [Unity 게임 개발] - [Unity 게임 개발 고수 되기 #1. Flappy..

codingwell.tistory.com

 

2020/03/11 - [Unity 게임 개발] - [Unity 게임 개발 고수 되기 #1. Flappy Bird ] 02. 기둥과 점수존 스폰/비활성화, 게임 오버, 점수 획득, UI 구현하기

 

[Unity 게임 개발 고수 되기 #1. Flappy Bird ] 02. 기둥과 점수존 스폰/비활성화, 게임 오버, 점수 획득, UI 구현하기

Flappy Bird 두 번째 포스트입니다! 아직 초보 개발자이니 부족한 부분은 의견 주시면 감사하겠습니당😊😊 그전에 첫번째 포스트를 못보신 분은 아래 링크 참고해 주세요! 2020/03/11 - [Unity 게임 개발] - [Unit..

codingwell.tistory.com

 

 

 

 

 

 

 

유니티로 구현하기

 

1. 메인메뉴 Scene 구현하기

이제 게임 진행 씬이 아니라 씬을 하나 더 만들어서 메인메뉴 화면을 구현해보겠습니당

Scene 을 하나 더 만들어주세요!

 

이렇게 Asset폴더에 Scenes 폴더를 하나 만드시는게 편할 것 같습니다.

 

만드셨다면 몇 개 오브젝트를 복사해서 붙여넣을 것이기 때문에

원래 Scene의 오브젝트 중에 Main Camera, Canvas, Event System, Floor, Player, 배경을 복사해주시고

새로만든 Main Menu Scene 으로 넘어가서 Hierarchy에 있는 것 다 지워주시고 붙여넣기해주세요.

 

 

 

 

 

메인메뉴 완성 화면은 이렇게 나와요.

 

메인 메뉴 완성 화면

일단 UI를 구현해볼게요. UI는 간단하게 원래있던 오브젝트 중에 RankingUI와 버튼 두개만 남겨주시고

FlappyBird라는 글자 이미지가 들어갈 오브젝트 하나만 있으면 될 것 같습니다.

 

UI 정리해주시고 Player만 (0,0,0)에 위치하면 될 것 같습니다.

 

 

 

 

 

 

 

 

 

 

2. 플레이어/배경 종류 랜덤으로 구현하기

실제 게임을 보시면,

플레이어가 색이 다르게 3가지 ( 파랑, 빨강, 노랑) 종류가 있습니다. 배경은 낮과 밤 이렇게 2가지 종류가 있죠.

이렇게 많은 종류들이 매번 게임을 시작할 때마다 랜덤으로 다르게 나타납니다. 

 

이것을 구현해보려고해요. 

일단 게임 어플에 들어가면 메인메뉴가 첫 화면이고,

메인메뉴에 나오는 배경과 플레이어의 종류가 재생버튼을 누른 후에 게임을 진행하는 화면에서도 이어집니다.

 

 

그 후에 게임을 진행하고 게임오버가 됩니다.

그럼 재생버튼을 눌러 게임을 다시 시작하겠죠?

이 때는 플레이어와 배경의 종류가 또 다르게 랜덤으로 나타납니다.

 

이러한 로직을 구현하기 위해서 일단, 플레이어 3개 종류와 배경 2개 종류 오브젝트를 만들겠습니다.

원래 있던 Player를 3개가 되도록 복사해주시고, 배경은 2개가 되도록 복사하고 이름을 바꿔주세요.

이렇게 만들어주시고, 각자 다른 Sprite를 넣어주세요.

그런데 여기서 , 문제가 생깁니다. Player가 게임 초반에 위아래로 움직이면서

날갯짓을 하는 애니메이션을 넣었었죠?

 

 

 

 

 

 

 

 

 

 

여기서 쓰이는 Sprite가 다르기 때문에 애니메이션을 따로 다 만들어주어야 합니다.

 

파랑색 플레이어의 애니메이션
빨강색 플레이어의 애니메이션

보시는 것처럼 날갯짓을 하는 Sprite가 다르게 쓰이기 때문에, 번거롭지만 세 종류 다 만들어주세요.

원래의 애니메이션을 복사해서 수정해주시면 금방 할 수 있습니다.

 

다 하셨다면, 만든 세 종류 플레이어 오브젝트와 배경 두 종류 오브젝트를 모두 복사하여 

게임 진행 Scene으로 가셔서 붙여넣기 해주시면 됩니다. 

 

 

 

 

 

 

 

 

※ 여기서 주의할 점!

 

메인 메뉴 화면에서는 플레이어가 (0,0,0) 중앙에 위치하죠?

그런데 게임 진행 화면에서는 플레이어가 약간 왼쪽에서 시작하기 때문에

게임 진행 Scene에서는 Player 오브젝트들을 빈 오브젝트 하나를 만들고

자식으로 종류들을 묶어주세요!

 

 

자식 오브젝트들의 Position은 (0,0,0)으로 해주시고,

감싸고 있는 빈 오브젝트는 (-1.2, 0, 0) 으로 해주세요.

상대적인 위치가 되어서 애니메이션에도 적용이 됩니다.

 

이제 모든 준비가 되었고, 랜덤 구현을 해보겠습니다.

만들었던 플레이어 3종류와 배경 2종류 오브젝트들을 모두 비활성화 해주세요.

게임을 시작할 때, 랜덤하게 선정된 플레이어와 배경 한 종류 씩만 활성화 시킬 겁니다!

 

 

 

 

 

 

 

 

다시 Main Menu Scene으로 넘어가주세요..!

여기서 게임진행 Scene의 GameManager 역할을 할 수 있는 빈 오브젝트를 하나 만들겠습니다.

 

저는 MainMenu 라고 빈 오브젝트를 하나 만들었습니다.

그리고 스크립트를 하나 만들어 넣어주세요.

이제 이 스크립트를 작성해보겠습니당

 

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

public class MainMenu : MonoBehaviour
{
    public int randomIndexA;
    public int randomIndexB;
    public Text[] scoreData;
    public GameObject[] players;
    public GameObject[] backgroundSprites;

    private void Start()
    {
        //플레이어와 배경의 sprite가 랜덤으로 적용되어 시작
        randomIndexA = Random.RandomRange(0, 3);  //0, 1, 2
        randomIndexB = Random.RandomRange(0, 2);  //0, 1

	//해당 오브젝트 활성화
        players[randomIndexA].SetActive(true);
        backgroundSprites[randomIndexB].SetActive(true);

        PlayerPrefs.SetInt("randomPlayer", randomIndexA); //플레이어 랜덤 값
        PlayerPrefs.SetInt("randomBg", randomIndexB); //배경 랜덤 값
        PlayerPrefs.SetInt("isReset", 1); //GameManager에서 상황 판단을 위한 값
        
        //점수 데이터 로드
        Load();
    }


    public void Retry() //게임을 다시 시작함
    {
        SceneManager.LoadScene(1);
    }

    private void Load() //랭킹 Panel의 text에 점수를 로드
    {
        scoreData[0].text = PlayerPrefs.GetInt("BestScore").ToString() + "점";
        scoreData[1].text = PlayerPrefs.GetInt("SecondScore").ToString() + "점";
        scoreData[2].text = PlayerPrefs.GetInt("ThirdScore").ToString() + "점";
    }


}

일단 재생 버튼과 랭킹 버튼을 구현하기 위해서 게임진행 Scene의 GameManager 스크립트에서 썼던 Retry함수와 Load함수를 가져왔습니다.

유니티에서 scoreData 배열에 적절하게 RankingUI의 Text 오브젝트들을 꼭 넣어주어야 합니다. 그리고 저번 포스트에서 했던 대로 재생 버튼, 랭킹 버튼, RankingUI의 Ok버튼 오브젝트 모두 유니티에서 Onclick()을 지정해주시면 됩니다. 

 

 

이제 정말 랜덤 구현을 해볼건데요,

위에서 말씀드렸던 것처럼 메인메뉴 Scene에서 선정된 플레이어/배경 종류가

게임 진행 Scene에 넘어가더라도 그대로여야 하기 때문에 여기서 PlayerPrefs를 사용하겠습니다. 

 

먼저 플레이어 오브젝트들을 넣어줄 게임오브젝트 배열 Players를 선언하고, 배경도 마찬가지입니다.

유니티에서 이 배열에 각각 플레이어 종류 세개와 배경 종류 두개를 꼭 넣어주세요.

 

Start 함수를 만들어주시고, 선언한 int형 변수에 Random 클래스를 사용합니다.

해당 오브젝트를 활성화 시켜주고,

PlayerPrefs를 사용하여 지정된 랜덤 변수 두개 데이터를 저장합니다.

 

저는 여기서 추가로 데이터를 하나 더 저장한 것을 볼 수 있는데, 이는 게임 진행 Scene에서 유효하게 사용됩니다.

게임 진행 Scene의 경우, 두가지 상황으로 나뉩니다.

- 메인메뉴에서 시작버튼을 누르고 게임진행 Scene으로 넘어왔다. --> 메인메뉴의 랜덤 값을 PlayerPref로 받아온다.

- 게임진행 Scene에서 게임 오버가 된 후, 다시 시작하기 위해 시작버튼을 눌렀다. --> 새로운 랜덤 값을 생성한다.

 

이 두 상황을 파악하기 위해 "isReset"이라는 데이터를 하나 더 저장하였습니다. 

이에 대해선 GameManager 스크립트를 수정할 때 자세히 보겠습니다.

 

 

 

 

 

 

 

 

 

이제 게임 진행 Scene의 GameManager 스크립트를 수정하겠습니당

변수 선언입니다. 랜덤 값 받을 두 int 형 변수를 선언하고 ScoreZone과 Floor 클래스를 가져옵니다.

그리고 아까 MainMenu 에서처럼 여러 오브젝트 종류들을 넣어줄 게임오브젝트 배열을 선언하고 유니티에서 꼭 넣어주세요.

int randomIndexA;
int randomIndexB;
public ScoreZone scoreZone;
public Floor floor;
public GameObject[] players;
public GameObject[] backgroundSprites;

 

void Awake()
    {
        scoreZone.gm = this;

        //캐릭터와 배경 랜덤 구현
        if (PlayerPrefs.GetInt("isReset") == 1)
        {
            randomIndexA = PlayerPrefs.GetInt("randomPlayer");
            randomIndexB = PlayerPrefs.GetInt("randomBg");
            PlayerPrefs.SetInt("isReset", 0);
        }
        else
        {
            randomIndexA = Random.RandomRange(0, 3);
            randomIndexB = Random.RandomRange(0, 2);
        }
        players[randomIndexA].SetActive(true);
        backgroundSprites[randomIndexB].SetActive(true);

        player = players[randomIndexA].GetComponent<Player>();
        floor.player = player;   
    }

Awake함수를 작성하겠습니다.

먼저 scoreZone에서 선언한 GameManager 클래스 변수 (gm)에 자신 (GameManager)을 할당하였는데요. 

ScoreZone을 프리펩으로 만들었기 때문입니다. 유니티에서는 프리펩 인스펙터에서 다른 오브젝트를 할당해줄 수가 없기때문에 저렇게 코드로 할당해주었습니다. 

 

이제 아까 저장하였던 데이터 "isReset"을 설명하겠습니다. 아까 1로 데이터를 넣었죠? 

메인메뉴에서 넘어온 상황일 경우 if문을 실행하게 되고, 저장된 데이터 값들을 가져온 후 "isReset"값을 0으로 바꿔주죠.

그리고, 게임 오버가 된후 다시 시작하는 상황에선 else문에 들어가게되고 다시 랜덤값을 생성하게 되겠죠?

 

선정된 랜덤값을 인덱스로하여 오브젝트를 활성화시켜주고, 

Player 클래스 변수에 현재 랜덤으로 선정된 오브젝트의 컴포넌트를 반환하면 되겠죠?

 

 

 

 

 

 

 

 

 

 

3. 효과음 구현하기

제가 첫번째 포스트에서 알려드렸던 링크에서 효과음 리소스를 다운받으셨다면, 유니티의 Assets에 드래그하여 넣어주세요.

저는 여러 효과음을 편하게 관리하기 위해서 Audio라는 빈오브젝트를 만든 후,

자식에 효과음 종류만큼 빈 오브젝트를 만들었습니다.

자식 오브젝트들에 모두 Audio Source 라는 컴포넌트를 추가해주세요.

그리고 각 효과음 오브젝트마다 다운받은 오디오 파일을

인스펙터창 Audio Source의 AudioClip에 드래그하여 넣어주시면 됩니당

 

 

형광펜 칠한 곳에 오디오 파일을 드래그하여 주세요.

그리고 효과음이기 때문에 꼭 Play On Awake와 Loop 항목은 체크가 빠져있어야 해요! 

- Play On Awake : Scene이 시작할 때 오디오를 재생

- Loop : 오디오를 계속해서 끝없이 재생

 

 

 

 

 

 

 

다 하셨다면, GameManager 스크립트를 수정해보겠습니다.

public AudioSource[] audio;

이와 같이 AudioSource 배열을 선언해주시고

유니티의 GameManager에서 효과음 오브젝트들을 드래그하여 꼭꼭 넣어주세요!

그리고 이제 적절한 시점에 오디오들을 재생시켜주어야 겠죠?

플레이어가 점프할 때 wing 효과음을 들려준다든지.. 게임 오버시에 hit와 die 효과음을 들려준다든지 말이죠!

 

 

 

 

 

 

 

예를 들어, 점수 획득할 때 point 효과음을 들려주기 위해서 ScoreZone 스크립트를 보면

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

public class ScoreZone : MonoBehaviour
{
    public GameManager gm;

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "Border")
        {
            gameObject.SetActive(false);
        }

        if(collision.gameObject.tag == "Player")
        {
            //점수 증가
            gm.score++;

            //점수 UI 업데이트
            gm.ScoreUpdate();

            //Sound
            gm.audio[2].Play();
        }
    }
}

플레이어와 ScoreZone이 닿을 때, GameManager클래스의 audio 배열을 호출하여 Play합니다.

상황에 맞는 적절한 효과음의 인덱스를 넣어 호출하면 됩니다.

 

스크립트들을 적절히 수정해서 5개의 효과음 모두 Play 문을 넣어주세요.

 

 

 

 

 

 

 

 

4. 모바일 빌드하기

계속해서 컴퓨터로 만드는 동안은 확인하기 위해서 스페이스로 점프를 구현했지만,

모바일로 게임을 하기 위해서는 터치로 구현을 해야합니다.

 

제가 첫번째 포스트에서 플레이어의 점프에 관해 코드 작성을 할 때,

스페이스 대신 터치 구현을 위해서 수정할 부분을 언급했었으니까 참고하고 고쳐주시면 됩니당!

 

마지막으로 Build Settings 에서

메인 메뉴와 게임 진행 Scene 인덱스가 0,1 차례대로 맞게 추가되어있는지 확인해주세요!  

 

 

모바일 빌드에 관해서 해야 할 것들은 아래 링크를 참고해주세요!!😎

https://spiritlink.tistory.com/16

 

유니티 안드로이드 APK 빌드 하기 (Unity to Android APK)

Unity로 만든 게임을 휴대폰 APK로 빌드해서 실행 해보자. Unity 설정변경 + NVIDIA Codeworks 에서 받은 파일을 설치, 빌드 할 예정이다. 유니티 메뉴중 File 메뉴 -> Build Settings 를 클릭한다. 빌드 설정을..

spiritlink.tistory.com

 

 

 


 

 

 

 

마지막으로 이 Flappy Bird의 소스코드와 어플이 있는 GitHub 링크 알려드리고 마치겠습니당

https://github.com/choijoohee213/FlappyBird

 

choijoohee213/FlappyBird

Unity Engine - Flappy Bird Game. Contribute to choijoohee213/FlappyBird development by creating an account on GitHub.

github.com

 

 

 

 

게임 실행 Youtube 영상입니다!

 

 

 

 

 

지금까지 Flappy Bird 게임을 만들어보았는데요!

이해가 잘 되셨으면 좋겠습니다😢

 

질문과 다양한 의견 주시기 바랍니당ㅎㅎ

감사합니다!😍

반응형
댓글
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday