본문 바로가기

study/unity

[unity] #7. 자동차 멈추기 게임

- 자동차 멈추기 게임

 

게임이 시작되면 왼쪽 아래에 자동차가 표시된다. 화면을 스와이프하면 자동차가 달리기 시작하다 점차 감속하면서 멈춘다. 스와이프 길이를 조절해서 자동차 주행거리를 바꿀 수 있다. 화면 오른쪽 아래에는 깃발이 표시되고 화면 가운데에는 자동차와 깃발 사이의 거리가 표시된다.

 

스와이프(Swipe): 손가락을 댄 후, 일직선으로 드래그하는 것을 말한다.

 

- 게임 설계

오브젝트 : 자동차(움직이는 오브젝트), 깃발, 지면, 거리를 표시하는 UI

자동차 -> 컨트롤러 스크립트 필요

자동차와 깃발 사이의 거리 UI -> 감독 스크립트 작성 필요

 

- 필요한 리소스 추가

 

 

ground
car
flag
배경색 -> 카메라 오브젝트에서 background DEDBD2

지금까지 실행 결과 - 오브젝트 배치, 배경색 변경

 

귀여워,,,

 

- 자동차 스크립트 작성

 

자동차를 움직이는 방법을 쓴 대본(컨트롤러 스크립트)이 필요하다.

1. 화면을 클릭하면 자동차가 움직이기 시작하고 서서히 감속해 멈추는 부분

 

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

public class CarController : MonoBehaviour
{
    float speed = 0;

    void Start()
    {
        
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0)) {
            this.speed = 0.2f;
        }
        transform.Translate(this.speed, 0, 0);
        //this.speed만큼 x축으로 이동
        this.speed *= 0.98f; //감속
    }
}

 

2. 스와이프 길이에 따라 자동차 이동거리 바꾸기

 

마우스 드래그 동작을 스마트폰의 스와이프 동작으로 생각한다.

스와이프 길이에 따라 자동차의 초기 속도를 결정한다.

 

스와이프 길이 계산 : 클릭을 시작한 좌표와 클릭이 끝난 좌표의 차이 구하기

클릭을 시작한 지점 -> GetMouseButtonDown

클릭이 종료한 지점 -> GetMouseButtonUp

각 지점의 마우스 좌표(Input.mousePosition)을 구하고 두 좌표의 차를 계산해서 스와이프 길이 값을 구한다.

 

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

public class CarController : MonoBehaviour
{
    float speed = 0;
    Vector2 startPos;

    void Start()
    {
        
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            //마우스 클릭 시작지점
            this.startPos = Input.mousePosition;
        }
        else if (Input.GetMouseButtonUp(0)) {
            //끝 지점
            Vector2 endPos = Input.mousePosition;
            float swipeLength = (endPos.x - this.startPos.x);

            //스와이프 길이를 speed에 대입
            this.speed = swipeLength / 500.0f;
        }


        transform.Translate(this.speed, 0, 0);
        //this.speed만큼 x축으로 이동
        this.speed *= 0.98f; //감속
    }
}

 

- UI 표시하기

 

UI는 게임의 상태나 진행 상황을 표시하는 것이다.

유니티에서는 UI부품 라이브러리가 제공되어 UI 설계를 간단히 할 수 있다.

 

UI를 만드는 방법

1. UI 부품을 Scene뷰에 배치한다.

2. UI를 갱신하는 감독 스크립트를 작성한다.

3. 빈 오브젝트를 만들고 작성한 스크립트를 적용한다.

 

Hierarchy창에서 Create를 클릭하고 UI -> Text 선택

Canvas인 오브젝트가 추가되고 Canvas 아래에 Text가 작성된다.

UI Text를 추가하면 Canvas와 EventSystem이 추가된다.

EventSystem은 사용자 입력과 UI부품을 중간에서 이어주는 오브젝트로 UI를 사용할 때 반드시 필요하다. EventSystem를 사용하면 입력 할당이나 무효화 등 키와 마우스 설정을 변경할 수 있다.

 

 

UI 설계화면은 일반적인 게임 설계화면보다 훨씬 크기가 크므로 추가한 글자가 Scene뷰에서 보이지 않을 수 있다.

이때는 Hierarchy창에서 Text를 더블클릭한다. 글자의 좌표 부근까지 시점이 이동한다.

 

 

 

UI 설계화면은 Scene뷰에서는 매우 크게 표시되지만 실제 크기는 게임화면에 맞춰진다.

 

세부 설정 변경

글자를 배치할 때 Rect Transform 항목이 Width와 Height 값이 표시할 문장 크기보다 작으면 글자가 화면에 제대로 표표시되지 않는다.

 

Scene -> 실행결과

 

- 감독 스크립트

 

감독 스크립트는 자동차와 깃발의 위치를 조사하고 둘 사이의 거리를 계산한 후 계산한 거리를 UI에 표시한다.

그러려면 스크립트에서 자동차, 깃발, UI 오브젝트를 다뤄야 한다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //UI 사용

public class GameDirector : MonoBehaviour
{
    //object 위치를 저장할 변수 선언
    GameObject car;
    GameObject flag;
    GameObject distance;

    void Start()
    {
        /* Find 메서드는 오브젝트명을 인수로 전달하고 
         * 인수명이 게임 씬 안에 있으면 해당 오브젝트를 반환한다.*/
        this.car = GameObject.Find("car");
        this.flag = GameObject.Find("flag");
        this.distance = GameObject.Find("Distance");
    }

    void Update()
    {
        float length = this.flag.transform.position.x - this.car.transform.position.x;
        this.distance.GetComponent<Text>().text = "목표 지점까지 " + length.ToString("F2") + "m";
        //F2 -> 소수점 둘째자리까지 표시
        //ToString -> 값을 문자열로 변환하는 메서드
    }
}

 

- 스크립트를 감독 오브젝트에 적용하기

 

스크립트를 오브젝트에 전달해야 한다. 완전히 빈 오브젝트를 만들고 그 오브젝트로 스크립트를 전달한다.

빈 오브젝트는 감독 스크립트를 전달하면서 감독 오브젝트로 변신해 감독 역할을 한다.

더보기

1. 감독 스크립트 작성

2. 빈 오브젝트 만들기

3. 빈 오브젝트에 감독 스크립트 적용

 

Hierarchy 창에서 Create Empty를 선택해서 빈 오브젝트를 만든다.

감독 스크립트를 드래그앤 드랍으로 적용한다.

 

 

 

 

 

 

 

실행 결과

 

- 컴포넌트

 

유니티 오브젝트는 GameObject라는 빈 상자에 설정 자료(컴포넌트)를 추가해서 기능을 늘릴 수 있다.

오브젝트를 물리적으로 움직이게 할 때 -> Rigidbody 컴포넌트 추가

소리를 내게 할 때 -> AudioSource 컴포넌트 추가

자체 기능을 늘리고 싶다면 -> 스크립트 컴포넌트 추가 (컨트롤러 스크립트, 감독 스크립트도 컴포넌트의 일종)

 

오브젝트의 회전을 관리하는 Transform 컴포넌트가 있다.

Transform 컴포넌트는 좌표, 회전, 이동과 같은 오브젝트의 움직임과 관련된 기능을 제공한다.

 

car.transform.position.x
/*자동차 오브젝트(car)에 적용한 Transform 컴포넌트에 있는
 *좌표(position) 정보로 접근*/

 

Transform 컴포넌트 이외에는 GetComponent 메서드를 사용하여 접근한다.

GetComponent는 게임 오브젝트에 대해 어떠한 컴포넌트를 달라고 하면 해당 컴포넌트(기능)을 돌려주는 메서드이다.

 

AudioSource 컴포넌트를 원하면 --> GetComponent<AudioSource>()

Text 컴포넌트를 원하면 --> GetComponent<Text>()

 

자신 이외의 오브젝트 컴포넌트에 접근하는 방법

1. Find 메서드로 오브젝트를 찾는다.

2. GetComponent 메서드로 오브젝트의 컴포넌트를 구한다.

3. 컴포넌트를 가진 데이터에 접근한다.

 

- AudioSource 컴포넌트 사용하여 효과음 넣기

 

1. 효과음을 낼 오브젝트에 AudioSource 컴포넌트 적용

2. AudioSource 컴포넌트에 효과음을 설정

3. 효과음을 울리고 싶은 시간에 스와이프 하면 Play 메서드 호출

 

Hierarchy창에서 car 클릭 --> Inspector창에서 Add Component -> Audio -> Audio Source 선택

 

Project 창에 있는 car_se를 Inspector창에 있는 Audio Source 항목의 AudioClip으로 드래그&드롭한다.

 

Play On Awake를 해제한다. 체크되면 게임을 시작한 시점에서 자동으로 소리가 재생된다.

 

 

 

 

 

 

 

효과음 재생 위해 스크립트에서 AudioSource 컴포넌트의 Play 메서드를 호출해야 한다.

아래의 효과음 재생 코드를 추가한다.

  else if (Input.GetMouseButtonUp(0)) {
            //끝 지점
            Vector2 endPos = Input.mousePosition;
            float swipeLength = (endPos.x - this.startPos.x);

            //스와이프 길이를 speed에 대입
            this.speed = swipeLength / 500.0f;

            //효과음 재생
            GetComponent<AudioSource>().Play();
        }

 

- 안드로이드에 빌드

자세한 설명은 아래의 글에 포함되어 있다.

2020/08/12 - [study/unity] - [unity] #6. 운세 룰렛

 

빌드중 ---

 

실행 결과

 

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