본문 바로가기

Projects/Individuals

[2D 플랫포머] Raining Money

 스파르타코딩클럽에서 제공된 게임개발종합반의 여러 예시에서 배운 것을 응용해 만들어보는 게임이다. 최대한 배운 모든 요소를 활용하려 한다. 우선, 이 글에서는 1주차 강의의 내용만을 활용해 게임을 만든 후, 새 주차마다 배우는 내용을 덧붙이는 방식으로 게임을 보완해 나가겠다. 

목   차

     


    1. 기본 씬 구성

    처음 Unity를 켜고 하는 기본적인 세팅 방법이다.

    레이아웃 및 기본 세팅

    1. 프로젝트 생성 후 레이아웃 2 by 3으로 바꾸기.
    2. project를 one column layout으로 하기.
    3. SampleScene을 MainScene으로 이름 바꾸기
    4. Game 씬 사이즈 바꾸기: Phone 세로사이즈(760 * 1280)

    유니티 개발 화면 개념

    • Scene: 실제 게임의 구성요소를 보는 곳. 실질적인 게임 개발 씬.
    • Game: 게임이 실제로 보여지는 곳. play 버튼 클릭 후 볼 수 있음.
    • Hiearchy: 게임 내 구성요소를 볼 수 있는 곳. 
    • Project: 이 프로젝트에 포함된 파일들을 모아볼 수 있는 곳.
    • Inspector: 클릭한 요소의 속성과 정보를 보여주는 곳.

    게임 배경 구성

    우선, MainScene을 우클릭하여 Sprites-Square을 생성하고 이름을 background라 붙인다. 그 후, SpriteRenderer의 Color에서 배경화면 색을 조절한다.(나는 (D7FFEA)색으로 했다.) 마지막으로, 카메라 크기에 딱 맞는 사이즈(x:6 y:10)으로 Transform의 Scale을 조정해준다.

    같은 방식으로, MainScene을 통해 또다른 Sprites-Square을 생성하고 이번에는 Ground라고 이름을 붙인다. SpriteRenderer의 Color 항목에서 색을 조정하고 Transform의 Scale을 (x:6, y:1.5)로 맞춘다. Position은 Y:-4.3으로 한다. 

    마지막으로 강의에서 제공된 르탄이 대신 ai로 제작한 이안이를 넣었다. 르탄이처럼 딱 2프레임으로 이루어진 이미지로, 오른쪽에 삽입된건 서 있는 버전이다. MainScene에 Square을 생성하고 Sprite Renderer의 Sprite에 이안 이미지를 드래그 앤 드롭으로 삽입했다. 그 후 사이즈를 적절하게 조절하고, Transform의 Position 값을 y:-2.9로 설정해 바닥에 잘 붙어있게 해주었다. 

     


    2. 애니메이션 맛보기

    애니메이션 만드는 과정

    1. 애니메이션 폴더 만들기(Assets > Animations)
    2. 애니메이션 파일 만들기
    3. 루프타임 필요하면 체크하기
    4. 캐릭터 sprite에 드래그 앤 드롭하기
    5. ".anim" 파일 더블클릭 후 애니메이션을 삽입할 sprite 클릭
    6. 애니메이션 파일들을 적당한 시간 간격으로 끌어다 두기.

    3. 캐릭터 움직이기

    Script 만들기

    1. Script 폴더 만들기 (Assets > Scripts)
    2. C# 스크립트 생성: 스크립트 이름=sprite 이름.
    3. 세부 동작 코딩.(Start: 객체 생성 시 할 동작. Update: 틱마다 실행될 동작.)

    ※중요※ 캐릭터 이동에 관한 함수/명령어 정리

    • 객체의 이동
      • transform.position.x += 1;
      • transform.position += new Vector3(x, y, z); //x, y, z의 단위는 float.
      • transform.position += Vector3.right; //left, up, down 등도 있음.
      • 이때 각 방향함수의 값은 1이다. 여기에 실수의 곱연산을 하는 식으로 속도를 조절할 수 있다.
    • 프레임을 일정하게 맞춰주는 코드
      • Application.targetFrameRate = N; //N은 초당 프레임.
    • 스프라이트 좌우반전
      • SpriteRenderer의 자료형으로 변수 선언 필요. (renderer이란 이름으로 설명함.)
      • renderer = GetComponent<SpriteRenderer>(); 을 Start함수에 삽입.
      • Update에서 필요할 때 renderer.filpX 또는 renderer.flipY 함수의 bool값을 조정함.
    • 마우스 클릭
      • Input.GetMouseButtonDown(0); 
      • 0: 좌클릭, 1: 우클릭, 2: 가운데 클릭. 

    4. 빗방울 구현하기

    빗방울(돈) 생성

    1. Sprites > Circle 생성, 금화 이미지 삽입.
    2. Rigidbody2D 삽입해서 중력의 영향을 구현한다.
    3. CircleCollider2D으로 물체의 충돌을 구현한다.
    4. 바닥에도 BoxCollider2D를 통해 충돌을 구현한다.

    ※중요※ 빗방울 충돌에 관한 함수/명령어 정리

    • OnCollisionEnter2D(Collision2D collision) 함수: 충돌을 감지.
      • 이때, collision은 이 객체가 충돌한 상대 물체.
    • collision.gameObject.CompareTag("태그") 를 통해 내가 부딪힌 객체가 "태그" 객체인지 아닌지 구분.
      • 이때 CompareTag 함수의 return값은 bool.
      • collision은 충돌 정보, gameObject는 충돌한 "객체".
    •  Tag 없이 하는 법: collision.gameObject.name == "Ground"로도 가능.(Tag 이용 추천)

    + Destroy(): 물체를 없애는 함수. 인자는 GameObject형.

    • 이때 collision.gameObject를 사용하면 상대객체를, this.gameObject를 사용하면 자신을 없앤다.

    ※중요※ 랜덤 빗방울 생성에 관한 함수/명령어 정리

    • 랜덤범위
      • Random.Range(범위1, 범위2);
      • 이 함수는 1 이상 2 미만의 범위에서 랜덤한 값을 뽑는다. 정수형을 사용할땐 2가 포함되지 않으니 주의할것.
    • 객체 사이즈 조절
      • transform.localScale = new Vector3(x, y, z);
      • 이때 인자의 자료형은 float.
    • 객체의 색상조절 하는 법.
      • SpriteRenderer 변수 선언. (변수명은 renderer로 설명함.)
      • renderer.color = new Color(R, G, B); //단, 1이 색상값 255를 뜻함. 또한, float형임.
      • 또는 HexToColor("#RRGGBB")

    ※중요※ 반복 생성에 관한 함수/명령어 정리

    • GameManager 만들기
      • MainScene 아래에 빈 GameManager 객체를 만든 후, GameManager 스크립트를 붙여넣는다.
    • GameManager에 반복생성할 GameObejct를 넣고, Unity의 GameManager 객체에서 선언되었던 변수 안에 적절한 Sprite 붙여넣기.
    • 반복생성할 함수 만들기
      • 우선, 생성 작업을 하는 함수를 만든다. (생성함수는 Initiate("GameObject"); )
      • InvokeRepeating("함수이름", float1, float2); //1은 N초 후 시작, 2는 반복시간.

    5. 점수 올라가게 하기

    점수판을 만드려고 보니 이안이가 서 있는 곳과 스코어보드를 구분하고 싶어져 잔디 이미지를 새로 만들어왔다. 다음이 그 결과다.

     

    점수보드 만들기

    1. Assets > Fonts 폴더 만들고 안에 원하는 폰트파일 넣기.
    2. UI > Legacy > Text 클릭, 폰트 사이즈, 위치 정하기.

    나는 3자리까지 점수를 추가할 수 있게 만들고 싶어서 딱 3자리 만큼의 공간이 나오게 만들었는데, 그럼 한자리수일 때 양 옆이 너무 허전해서 000~999처럼 한 자리 수라도 0을 추가해 3자리로 보이게 만들 것이다. 또 시간 초도 0.1초 단위까지만 보이게 했다.

     

    ※중요※ 싱글톤

    싱글톤 패턴: 소프트웨어 디자인 패턴 중 하나로, 해당 클래스의 인스턴스(객체)가 단 하나만 생성되도록 보장하는 패턴. 전역상태나 공유자원에 대한 접근을 제한할 때 사용하며, 이 수업에서는 주로 GameManager에서 필요하다.

     

    다른 소프트웨어 디자인 패턴들:

    더보기
    • 팩토리(Factory) 패턴: 객체 생성에 대한 책임을 하위 클래스나 하위 객체에게 위임하여 유연성을 높이는 패턴입니다. 객체 생성 로직을 캡슐화하여 객체 생성 방식을 변경하거나 새로운 종류의 객체를 동적으로 생성할 수 있습니다.
    • 스트래티지(Strategy) 패턴: 알고리즘을 정의하고 각각을 캡슐화하여 교체할 수 있도록 만드는 패턴입니다. 실행 중에 알고리즘을 변경하거나 확장할 수 있으며, 코드 재사용과 유지보수성을 높일 수 있습니다.
    • 옵저버(Observer) 패턴: 객체 사이의 일 대 다 의존성을 정의하는 패턴입니다. 한 객체의 상태가 변경되면 그와 관련된 다른 객체들에게 알림을 전달하여 상호작용을 수행할 수 있습니다.
    • 데코레이터(Decorator) 패턴: 객체에 동적으로 새로운 기능을 추가하는 패턴입니다. 객체의 구조를 변경하지 않고도 객체의 기능을 확장할 수 있습니다.
    • 팩토리 메서드(Factory Method) 패턴: 객체를 생성하기 위한 인터페이스를 정의하지만, 구체적인 클래스는 서브클래스에서 결정하도록 하는 패턴입니다.
    • 추상 팩토리(Abstract Factory) 패턴: 관련 있는 객체들의 집합을 생성하기 위한 인터페이스를 제공하는 패턴입니다. 여러 종류의 객체 집합을 생성하고 이에 대한 인터페이스를 제공합니다.

     

    * 챗 GPT를 이용해 꼽고 정의한 기본적인 패턴들으로, 필자도 아직 이에 대한 공부가 부족해 잘못되거나 자주 쓰이지 않는 패턴이 있을 수 있음.

    1주차 수업에서 싱글톤을 만드는 방법은 다음과 같다:

    1. GameManager형의 변수 Instance를 public static으로 선언한다.
    2. private void Awake()함수를 선언하고, Instance = this; 을 통해 현재 객체를 static 변수로 선언한다.

    Text UI와 코드 연동하기.

    1. public으로 선언된 AddScore 함수를 통해 총 점수를 구한다.
    2. 이안이를 태그를 통해 특정할 수 있도록 Player 태그를 부여한다.
    3. Rain 스크립트의 OnCollisionEnter2D 함수에서 Player와의 Collision을 감지하고, 그에 따라 점수를 올리게 코딩한다.
    4. Player에게 Collider Component를 삽입하고, Collision 크기조정을 한다.
    5. GameManager에서 using UnityEngine.UI 패키지를 삽입하고 Text 타입 변수를 선언한다.
    6. 이 Text변수.text = ((String타입 문자열)) 을 삽입해준다. 
      • 문자열이 아닌 변수는 .ToString() 함수를 이용하면 된다. 
      • 괄호 안에 인자로 "Nx"를 넣으면 x만큼의 소숫점 자리까지 표시된다.
    7. Unity에서 GameManager 컴포넌트에 변경할 텍스트 Hiearchy를 삽입한다.

    6. 게임 끝내기

    우선, 게임오버 UI를 만든다. 방식은 UI에서 Image를 먼저 삽입하고, 그 하위항목으로 Text를 삽입하면 된다. 이 부분은 위에서 했던 부분이므로 자세한 설명은 생략한다. 또한, 시간이 흐르고 멈추게 하는 것 역시 위의 점수 UI 바꾸는 것과 같은 원리이므로 역시 생략했다.

    판넬 컨트롤하기

    1. endPanel을 GameManager에 GameObject형으로 선언한다.
    2. endPanel.SetActive(bool)을 통해 보이거나 안보이게 한다.
    3. 판넬에 button Component를 달고 Button을 조종할 Script를 만들어준다.
    4. Script에 Button이 할 동작(여기서는 SceneManager.LoadScene("씬이름"))을 삽입해준다.
    5. Onclick 연결해준다. (Runtime 아래에 스크립트 끌어오기 + 함수 설정하기)
    6. GameManager에서 초기화해야 하는 요소 초기화해주기.

    마무리

    한 주차를 하루만에 유사한 게임으로 재탄생시킬 수 있다고 오만한 생각을 했다가 에셋 만들기에 하루, 캐릭터 움직임 구현까지 하루, 빗방울 만드는데 또 하루, 완성하는데 나머지 하루를 써서 생각보다 TIL의 완성 및 공개가 훨씬 길어져버렸다. 다음에는 딱 하루치 내용만 그때그때 업로드하고 만약 하루가 다 가게 된다면 1-1, 1-2 이런 식으로 분할해서 업로드 해야겠다.