유니티(Unity)

룰렛 & 자동차 멈추기 게임

염두리안 2025. 4. 21. 16:36
728x90
반응형

프레임레이트를 60으로 고정하는 이유 : 디바이스에 따라 성능 차이가 있다면 게임 동작에 영향을 미칠 수 있기 때문... 이 차이를 없애고자 60으로 FPS 고정

Application.targetFrameRate = 60;

 

게임 설계

  1. 화면에 놓일 오브젝트 모두 나열하기
  2. 오브젝트를 움직일 수 있는 컨트롤러 스크립트를 정함
    • 움직이는 오브젝트에 오브젝트의 움직임을 제어하는 대본 필요 => 컨트롤러 스크립트
  3. 오브젝트를 자동으로 생성할 수 있도록(게임 플레이시 생성될 오브젝트) 제너레이터 스크립트를 정함
  4. UI를 갱신할 수 있도록(UI를 조작하거나 진행상황을 판단) 감독 스크립트를 준비
  5. 스크립트를 만드는 흐름을 생각
    • 기본적으로 컨트롤러 스크립트 → 제너레이터 스크립트 → 감독 스크립트 순으로 제작

 

각 축의 회전 방향

  • 2D 룰렛 돌리기의 경우, Z축 회전이 적합

  • Rotate 메소드 : 오브젝트를 회전시킴 | 양수면 시계 반대 방향, 음수면 시계 방향으로 회전
// transform.Rotate(x축, y축, z축);
transform.Rotate(0, 0, this.rotspeed);

 

마우스로 입력 받기

  • GetMouseButtonDown : 클릭된 순간 true 반환(누르고 있는 동안 계속 반환)
  • GetMouseButtonUp : 마우스 왼쪽 버튼에서 손가락을 뗀 순간 한 번만 true 반환
Input.GetMouseButtonDown(0)

 

회전 속도 줄이기

  • rotSpeed에 값을 조금씩 줄이면 일정 속도(선형)로 감속하기 때문에 움직임이 자연스럽지 않음...
  • 따라서 각 프레임의 rotSpeed 값에 감쇠 계수(ex. 0.96)를 곱하면 됨!
  • 이 방법은 선형함수가 아닌 지수함수처럼 감속하므로 자연스럽게 감속하는 것처럼 보임
  • 감쇠 계수를 변경하는 것만으로도 감속 크기를 쉽게 바꿀 수 있기 때문에 공기 저항에 따른 감속이나 스프링 진동 감쇠 등 다양한 장면에서 사용
  • rotSpeed는 결코 0이 되진 않지만, 매우 작은 수라 룰렛이 정지한 것 처럼 보임
this.rotSpeed *= 0.96f;

 

안드로이드 빌드하기(왜냐면 내 폰이 안드로이드니까...)

  • 제작할 때 Platform을 Android로 설정
  • [메뉴바] - [File] - [Build Settings]
  • Build Settings 창에서 [Player Settings] - [Company Name] 설정
  • Build Settings로 돌아가 Scenes In Build에서 Project의 GameScenes를 여기로 드래그&드롭
  • 마지막으로 [Build And Run] 해서 저장하면 apk 파일 생성 완료 ~ !

 


클릭하면 자동차가 달리다가 서서히 멈추는 스크립트

  • Translate 메서드 : 게임 오브젝트를 현재 좦에서 인수 값만큼 이동시키는 메서드 | 인수가 현재 좌표 값을 직접 나타내는 것은 X, 현재 좌표의 상대적인 이동 값을 나타냄
  • 월드좌표계와 로컬 좌표계
    • 월드 좌표계 : 오브젝트가 게임판 어디에 있는지 나타냄
    • 로컬 좌표계 : 게임 오브젝트가 개별적으로 갖는 좌표계 | Translate 메서드 사용시 이동방향은 로컬 좌표계로 계산됨
  • 스와이프 길이에 따라 자동차 이동 거리 바꾸기 : (클릭을 시작한 좌표와 클릭이 끝난 좌표의 차이)를 구하여 사용
    • GetMouseButtonUp - GetMouseButtonDown
public class CarController : MonoBehaviour
{
    float speed = 0;	// 현재 자동차 속도
    Vector2 startPos;	// 마우스를 처음 눌렀을 때의 위치

    void Start()
    {
        Application.targetFrameRate = 60;
    }

    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;	// 스와이프의 거리 = 끝 - 시작

            // 스와이프 길이를 처음 속도로 변경한다
            this.speed = swipeLength / 500.0f;
        }

        transform.Translate(this.speed, 0, 0);  // 이동
        this.speed *= 0.98f;                    // 감속
    }
}

 

Text를 사용해 거리 표시하기

  • [우클릭] - [UI] - [Text-TextmeshPro] 로 텍스트 생성
    • TMP Impoerter창이 나타나면 [Import TMP Essentails] 를 하고 임포트가 끝나면 창 닫기
  • Hierarchy에 [Canvas] - [Text(TMP)] 생성
    • 텍스트 오브젝트 이름 수정시 Text(TMP) 를 수정해서 사용 (여기선 Distance로 사용)
  • Find 메서드 : 오브젝트 이름을 인수로 전달하고 인수 이름이 게임 씬 안에 있으면 해당 오브젝트를 반환
    • 이때, Hierarchy창에 표시된 이름과 동일하게 지정해야 함
  • ToString
    • 정수형 D[자릿수] : 정수를 표시할 때 사용 | 지정한 자릿수를 채우지 않으면 왼쪽에 0 삽입
      • (456).ToString("D5") → 00456
    • 고정 소수점형 F[자릿수] : 소수 표시할 때 소수점 이하 자릿수를 지정 | 끝 수는 반올림
      • (12.3456).ToString("F3") → 12.346
  • 이 스크립트의 경우, Distance (Text오브젝트)가 아닌, GameDirector라는 감독 오브젝트에 따로 적용해야 함
using UnityEngine.UI;  // UI를 사용하는 데 필요
using TMPro; // TextMeshPro 사용시 필요

public class GameDirector : MonoBehaviour
{
    GameObject car;	// 자동차
    GameObject flag;	// 목표지점
    GameObject distance;	// 남은 거리를 표시할 UI 텍스트

    void Start()
    {
        this.car = GameObject.Find("car");
        this.flag = GameObject.Find("flag");
        this.distance = GameObject.Find("Distance");
    }

    void Update()
    {
        // 자동차와 깃발의 x좌표 차이를 계산하여 length에 저장
        float length = this.flag.transform.position.x - this.car.transform.position.x;
        // length 값을 소수점 둘째자리까지 포맷 문자열로 바꾸고 UI 텍스트에 표시
        this.distance.GetComponent<TextMeshProUGUI>().text = "Distance: " + length.ToString("F2") + "m";
         }
    }
  • 만약 한국어를 표시하고 싶다면?
    • 사용하고 싶은 폰트 파일을 다운 받고(.ttf, .otf) 프로젝트 창으로 드래그&드롭
    • 스프라이트 폰트를 만듦
      • 스프라이트 폰트? 앱에서 사용하는 모든 문자를 스프라이트에 그린 것
      • Window - TextMeshPro - Font Asset Creator
      • Font Asset Creator가 열리면 Source Font에 프로젝트에 추가한 폰트 파일을 지정
      • Character Set을 Custom Charactoers로 하고, Custorm Character List에 앱 안에서 사용하는 한국어를 모두 입력
      • Generate Font Atlas 클릭 후 Save
    • Hierarchy 창에서 한국어를 표시하고 싶은 Text(TMP) 오브젝트 선택
    • Inspector - TextMeshPro - Text 컴포넌트에서 Font Asset  ⊙ 선택해서 스프라이트 폰트 선택하면 끝 ~ !

 

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

  1. Find 메서드로 오브젝트를 찾는다.
  2. GetComponent 메서드로 오브젝트의 컴포넌트를 구한다.
  3. 컴포넌트를 가진 데이터에 접근한다.

 

효과음 사용하기

  1. 효과음을 낼 오브젝트에 AudioSource 컴포넌트를 적용한다.
  2. AudioSource 컴포넌트에 효과음을 설정한다.
  3. 효과음을 울리고 싶은 시간에 스와이프를 하면 Play 메서드를 호출한다.
  • 그래서 어떻게 넣는데? [오브젝트] 선택 - [Inspector] - [Add Component] - [Audio] - [Audio Source] 선택 후 오디오 항목을 Audio Resource로 드래그&드롭
// 효과음을 재생한다
GetComponent<AudioSource>().Play();
728x90
반응형