본문 바로가기

study/unity

[unity] #8. 화살 피하기 게임 - 1

- 화살 피하기 게임

 

화면 가운데 플레이어, 오른쪽 위에는 HP 게이지를 표시한다. 화살이 위에서 아래로 떨어지고 플레이어를 좌우 화살표 버튼을 움직여 화살을 피한다. 플레이어가 화살에 맞으면 HP 게이지가 줄어든다.

 

- 게임 설계

 

오브젝트 : 플레이어, 화살, 배경, 이동 버튼, HP 게이지

1. 움직이는 오브젝트 : 플레이어, 화살 --> 컨트롤러 스크립트 필요

2. 게임을 플레이할 때 생성될 오브젝트 : 화살 --> 제너레이터 스크립트 필요

더보기

게임 도중에 오브젝트를 자동 생성하려면 생성을 담당할 공장이 필요하다. 공장을 가동시키기 위해서 제너레이터 스크립트가 필요하다.

화살 제너레이터 --> 화살을 1초에 1개씩 생성

3. 진행 상황을 보면서 UI를 갱신하는 감독 : HP 게이지 --> 감독 스크립트 필요

 

 

 

나중에 안드로이드 빌드 위해 Platform 변경

 

 

 

- 필요한 리소스 추가

 

 

 

 

 

player
background 이미지 추가

 

 

- 레이어 설정

 

위의 사진에서 보이듯이 플레이어가 배경 이미지 뒤에 놓여 화면에 플레이어가 보이지 않는다.

유니티의 2D 게임에서 각 게임 오브젝트는 레이어 번호를 갖고 있고, 이 번호에 따라 화면에 놓일 앞뒤 위치가 결정된다. 레이어 번호가 클수록 화면 앞쪽(겉)에 표시되고 작을수록 화면 뒤쪽(속)에 표시된다.

 

현재 플레이어와 배경 이미지의 레이어 번호가 모두 0이다. 플레이어 이미지를 배경 이미지 앞에 배치하기 위해 레이어 번호를 1로 키운다.

 

 

 

Order in layer를 1로 설정

 

 

- 플레이어 스크립트 작성하기

 

여기서는 화살표 키 입력에 맞춰 플레이어가 움직이도록 만들 것이다.

최종적으로는 화면에 있는 버튼을 누르면 플레이어가 움직이도록 만든다. 

 

Project창 오른쪽 마우스 클릭 --> Create --> C# script 선택 --> PlayerController로 이름 변경

 

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

public class PlayerController : MonoBehaviour
{
    void Start()
    {
        
    }

    void Update()
    {
        /*
         * GetKeyDown : 매개변수로 전달한 키가 눌리는 순간 true를 1번 반환
         */


        if (Input.GetKeyDown(KeyCode.LeftArrow)) { //왼쪽 화살표 버튼 눌릴때
            transform.Translate(-3, 0, 0); //왼쪽으로 3 이동
        }

        if (Input.GetKeyDown(KeyCode.RightArrow)){ //오른쪽 화살표 버튼 눌릴때
            transform.Translate(3, 0, 0); //오른쪽으로 3 이동
        }
    }
}

 

키 버튼을 꾸욱 누르고 있어도 이동은 1번만 하게 된다.

GetKeyDown -> 누른 순간 true반환

GetKeyUp -> 누르고 손을 뗀 순간 한번 true반환

GetKeyDown -> 누르고 있는 동안 계속 true반환

 

실행 결과

 

- 화살 떨어트리기

 

유니티에 내장된 Physics 기능을 사용하면 유니티가 중력을 계산해 주므로 스크립트를 쓰지 않고도 화살을 떨어트릴 수 있다. 단, Physics를 사용하면 직접적인 움직임(정밀한 표현 등)을 처리하기가 어렵다. 따라서 여기서는 Physics를 사용하지 않고 위와 동일한 방식으로 화살을 위에서 아래로 떨어트릴 것이다.

 

 

 

arrow 리소스 추가

 

 

위와 동일하게 스크립트 작성 --> ArrowController

 

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

public class ArrowController : MonoBehaviour
{
    void Start()
    {
        
    }

    void Update()
    {
        //프레임마다 등속으로 낙하시킨다.
        transform.Translate(0, -0.1f, 0);

        //화면 밖으로 나오면 오브젝트를 소멸시킨다.
        if (transform.position.y < -5.0f) {
            Destroy(gameObject);
        }
    }
}

 

화면 밖으로 나온 화살은 소멸시킨다

--> 화살이 보이지 않는 곳에서 계속 떨어지면 메모리가 낭비된다. 따라서 화살이 화면 밖으로 나가면 오브젝트를 소멸시킨다. 화살의 y좌표 값이 화면 아래쪽(y = -5.0)보다 작아지면 Destroy 메서드를 써서 자신(화살 오브젝트)을 소멸시킨다. Destroy 메서드는 매개변수로 전달한 오브젝트를 삭제할 때 쓴다.

 

게임을 실행하면 화살이 화면 밖으로 나가면 Hierarchy창에서도 arrow가 사라지는 것을 확인할 수 있다.


실행 결과

 

- 충돌 판정

 

충돌 판정은 게임에서 오브젝트끼리 충돌한 것을 감지하는 구조이다. 게임을 만들 때 아무것도 설정하지 않으면 오브젝트끼리 충돌해도 그냥 통과하게 된다. 이를 막기 위해 오브젝트끼리 충돌하는지 항상 감시하고, 충돌하면 특정한 처리를 해준다. 

 

1. 충돌을 감지하는 부분 --> 충돌 판정

2. 충돌을 감지한 다음 움직임을 정하는 부분 --> 충돌 반응

 

간단한 충돌 판정 --> 오브젝트의 형상을 단순하게 원형이라고 가정한다. 원형은 오브젝트의 윤곽을 확인하지 않아도 원의 중심 좌표와 반경을 알면 충돌 판정을 간단히 할 수 있다.

 

 

충돌 판정 상세 설명

 

아이패드 없는 나는 메모지에다가 끄적끄적 히.. 아이패드 사고싶.......다.............

 

- 충돌 판정 스크립트 작성 (ArrowController에 추가)

 

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

public class ArrowController : MonoBehaviour
{
    GameObject player;

    void Start()
    {
        this.player = GameObject.Find("player");
    }

    void Update()
    {
        //프레임마다 등속으로 낙하시킨다.
        transform.Translate(0, -0.1f, 0);

        //화면 밖으로 나오면 오브젝트를 소멸시킨다.
        if (transform.position.y < -5.0f) {
            Destroy(gameObject);
        }

        //충돌 판정(추가)
        Vector2 p1 = transform.position; //화살 중심 좌표
        Vector2 p2 = this.player.transform.position; //플레이어 중심 좌표
        Vector2 dir = p1 - p2;

        float d = dir.magnitude; //dir의 길이
        float r1 = 0.5f; //화살 반경
        float r2 = 1.0f; //플레이어 반경

        //충돌한 경우 화살 지우기
        if (d < r1 + r2) {
            Destroy(gameObject);
        }

    }
}

 

실행결과

녹화 잘 안되서 결국 ShareX 깔았다.. 윈도우 본계정은 녹화 되는데 영어이름 계정은 뭔가 이상...

 

출처 : <유니티 교과서 개정 3판> 책