8. 들어가기 전에
이 장에서는 UI 를 만들고, 게임의 규칙을 관리하고 게임오버 상태를 표현하는 게임 매니저를 만든다. 그리고 남은 게임 요소를 완성하고 게임을 빌드하여 닷지를 최종 완성한다.
레트로의 유니티 게임 프로그래밍 에센스 | 이제민 - 교보문고
레트로의 유니티 게임 프로그래밍 에센스 | 이제민 - 교보문고
레트로의 유니티 게임 프로그래밍 에센스 | 독자분들로부터 수많은 찬사를 받았던 유니티 대표 도서 『소문난 명강의:레트로의 유니티 게임 프로그래밍 에센스』가 개정판으로 돌아왔습니다!
product.kyobobook.co.kr
8.1 프로젝트 정리
게임을 완성하기 전에 프로젝트 창에 폴더를 만들어 에셋과 스크립트를 정돈한다.
유니티 프로젝트의 Assets 폴더 내부에 또 다른 폴더를 만들고 에셋의 경로를 수정하는 것은 프로젝트와 씬에 영향을 미치지 않는다. 예를 들어 프로젝트 내에서 머티리얼을 저장한 폴더를 변경한다고 해서 해당 머티리얼을 사용한 게임 오브젝트가 망가지지 않는다.
1. 정리를 위한 폴더 생성
- 프로젝트 창에서 새로운 폴더를 만들고 Scripts 로 이름 변경
- 새로운 폴더를 만들고 Materials 로 이름 변경
- 새로운 폴더를 만들고 Prefabs 로 이름 변경
![](https://blog.kakaocdn.net/dn/2LWhW/btsMcsbjwni/knyu2zNEqrhlEK9aRO40g0/img.png)
2. 에셋을 종류별로 폴더에 정리하기
- 스크립트 에셋은 Scripts 로
- 머티리얼 에셋은 Materials 로
- 프리팹 에셋은 모두 Prefabs 로
![](https://blog.kakaocdn.net/dn/bNvKmw/btsMdm2ESwR/UpwfFdXS6hS2HIQloTsB31/img.png)
8.2 바닥 회전
플레이어 아래의 바닥을 일정 속도로 회전시킨다. 바닥 회전 기능을 스크립트로 구현하여 Level 게임 오브젝트에 적용한다.
8.2.1 Rotator 스크립트 준비
게임 오브젝트를 일정 속도로 회전시키는 Rotator 스크립트를 작성한다.
1. Rotator 스크립트 생성
- Scripts 폴더로 이동
- 새로운 스크립트 만들고 Rotator 로 이름 변경
![](https://blog.kakaocdn.net/dn/bKWI7L/btsMcgB7AAS/JHStwnXqVHBUMCuVeGV07k/img.png)
2. Rotator 스크립트에 변수 생성
rotationSpeed 는 게임 오브젝트가 1초에 Y 축을 기준으로 몇 도 회전할지 나타낸다. 게임 오브젝트를 회전시키는 데 트랜스폼 컴포넌트에 내장된 Ratate() 메서드 사용.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotator : MonoBehaviour
{
// 게임 오브젝트가 1초에 Y축 기준 몇 도 회전할지 나타낸다.
public float rotationSpeed = 60f;
void Update()
{
transform.Rotate(0f, rotationSpeed, 0f);
}
}
위 코드는 오류가 있다. 1초에 60도를 회전하는 것을 원했지만 위는 매 프레임마다 60도 회전한다.
3. Rotator 스크립트 적용
- Rotator 스크립트를 Level 게임 오브젝트로 드래그&드롭
![](https://blog.kakaocdn.net/dn/coIiB2/btsMcznRaUY/EdfoDIzcChLQrTucRshfek/img.png)
비정상적인 속도로 Level 게임 오브젝트가 회전한다. 이것은 의도한 동작이 아니다.
작성한 코드의 문제는 transform.Rotate(0f, rotationSpeed, 0f) 가 1초에 600도 회전하는 코드가 아니라 한 번(한 프레임) 에 60도 회전한다는 것. 그리고 한 번에 60도 회전하는 코드를 Update() 메서드로 1초에 60번 이상 실행했다.
8.2.2 속도와 시간 간격
Update() 메서드는 게임 화면이 한 번 갱신될 때 1회 실행된다. 이는 평균적으로 1초에 60번 실행된다. 하지만 이는 평균일 뿐 게임 화면을 갱신하는 주기는 컴퓨터 성능에 의존적이라 Update() 가 1초에 몇 번 실행될지는 알 수 없다.
따라서 Update() 메서드에서 초당 이동 속도나 회전 속도 등 시간과 관련된 수치를 다룰 때는 시간 간격을 고려해야 한다. 그렇지 않으면 컴퓨터 성능에 따라 같은 코드가 다르게 동작할 수 있다.
이를 해결하는 방법은 시간 간격으로 쪼개서 누적하는 것이다. 정답은 초당 프레임의 역수를 회전값에 곱한다. 1초에 코드가 실행되는 횟수 60에 역수를 취하면 1/60이다. 이렇게 구한 값은 직전 프레임과 현재 프레임 사이의 시간 간격이 된다. 그리고 해당 값을 회전 속도인 60도에 곱한다. 그러면 1초 동안 원래 의도했던 초당 회전값이 나온다.
(60도 회전) * (1/60) * (60번 실행) = 총 60도 회전
이 방법은 Update() 가 1초에 몇 번 실행되는 상관없이 적용할 수 있다. 결론은 초당 프레임의 역수를 취한 값을 곱하면 한 번에 x만큼 이동에서 1초 동안 x만큼 이동을 구현할 수 있다.
7.5.4 절에서 Time.deltaTime 이 이전 프레임과 현재 프레임 사이의 시간 간격이라는 것을 배웠다. Time.deltaTime 은 프레임의 주기이자 초당 프레임에 역수를 취한 값이다. Time.deltaTime 을 이용하여 지금까지 설명한 해결 방법을 구현할 수 있다.
8.2.3 Rotator 스크립트 수정
1. Rotator 스크립트 수정
스크립트가 완성되었다. 저장하고 씬으로 돌아간다. 플레이 버튼을 눌러 씬으르 테스트해보면 Level 게임 오브젝트가 이전과 달리 정상적인 속도로 회전한다. 동작을 확인했으면 플레이 모드를 해제하고 씬을 저장한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotator : MonoBehaviour
{
// 게임 오브젝트가 1초에 Y축 기준 몇 도 회전할지 나타낸다.
public float rotationSpeed = 60f;
void Update()
{
transform.Rotate(0f, rotationSpeed * Time.deltaTime, 0f);
}
}
8.3 게임 UI 제작
생존 시간, 게임 오버, 최고 기록을 표현하는 UI 를 만든다.
유니티의 UI 시스템은 UI 요소를 게임 월드 속의 게임 오브젝트로 취급한다. 즉, 하나의 UI 요소는 씬 속의 하나의 게임 오브젝트가 된다. UI 게임 오브젝트를 씬 내부에서 편집한다. 그러므로 일반 게임 오브젝트를 다루는 방법과 같은 방법으로 UI 게임 오브젝트를 다룰 수 있다는 장점이 있다.
8.3.1 생존 시간 텍스트 제작
닷지 게임에서는 탄알을 피해 생존한 시간이 점수와 같은 의미를 가진다. 따라서 게임이 시작된지 몇 초가 지났는지 표시할 UI 가 필요하다.
씬 편집 모드를 2D 모드로 바꿔 UI 를 편집하기 쉽게 하고, 시간을 표시하는 UI 텍스트 게임 오브젝트를 만든다.
1. UI 텍스트 만들기
- 씬 창에서 2D 버튼 클릭 -> 2D 편집 모드로 전환
- 하이어라키 창에서 + > UI > Legacy > Text 클릭
- 하이어라키 창에서 Canvas 더블 클릭 -> 씬 창에서 Canvas 가 포커스 됨
![](https://blog.kakaocdn.net/dn/xi3Qm/btsMbtvvFPQ/6MGw0E1OmfaVKSDDG0QN8K/img.png)
Text 게임 오브젝트를 만드는 순간 총 세 개의 게임 오브젝트가 생성되는 것에 주목한다. 텍스트뿐만 아니라 캔버스와 이벤트 시스템 게임 오브젝트가 함께 생성된다.
캔버스와 이벤트 시스템
Text 게임 오브젝트는 Canvas 게임 오브젝트의 자식 오브젝트로 설정되어 있다. UI 요소들은 캔버스의 2차원 평면에 배치되기 때문이다. UI 게임 오브젝트는 일반 게임 오브젝트와 달리 트랜스폼 컴포넌트를 확장한 사각 트랜스폼 컴포넌트를 갖는다. 즉, UI 요소는 자신이 배치될 2차원의 액자가 필요하고 Canvas 게임 오브젝트는 UI 요소가 배치될 수 있는 액자 역할을 한다.
따라서 UI 게임 오브젝트를 만들 때 Canvas 게임 오브젝트가 씬에 없다면 자동으로 하나 생성된다. 그리고 모든 UI 게임 오브젝트는 Canvas 게임 오브젝트의 자식이 되어야 한다.
EventSystem 게임 오브젝트는 이벤트 시스템 컴포넌트를 가진 게임 오브젝트로, UI 게임 오브젝트에 클릭이나 터치, 드래그 같은 상호작용을 이벤트 메시지로 전달한다. 이 게임 오브젝트가 없다면 UI 버튼이나 슬라이드 바를 클릭하고 드래그하는 등의 UI 상호작용을 할 수 없다.
8.3.2 텍스트 배치
생성된 Text 게임 오브젝트의 위치는 책과 다를 수 있다. 따라서 Text 게임 오브젝트의 이름을 변경하고 캔ㅂ서스 중앙 상단으로 정렬하여 배치한다. 그러면 게임 화면 중앙 상단에 보인다. UI 게임 오브젝트를 정렬할 때는 앵커프리셋을 사용한다.
1. UI 텍스트 정렬하기
- Text 게임 오브젝트의 이름을 Time Text 로 변경
- 인스펙터 창에서 앵커 프리셋 클릭 -> 앵커 프리셋 창이 열림
- [Alt] 키를 누른 상태에서 top-center 클릭
앵커 프리셋을 연 상태에서 [Alt] 키를 누르면 스냅핑이 활성화된다. 이 상태에서는 앵커값 뿐만 아니라 포지션값도 변경되며, UI 게임 오브젝트가 해당 방향의 모서리에 달라붙는 형태로 정렬된다.
![](https://blog.kakaocdn.net/dn/cEpFDI/btsMcYOmouL/rDkHQJULk09RRasgqWat6K/img.png)
8.3.3 텍스트 꾸미기
UI 텍스트를 배치했으니 텍스트 내용과 폰트 색깔을 변경한다. Text 게임 오브젝트에 추가된 텍스트 컴포넌트가 UI 텍스트로 동작하고 출력되는 내용을 결정한다.
1. Time Text 의 텍스트 변경하기
- Time Text 게임 오브젝트의 Text 컴포넌트의 Text 필드 내용을 Time : 0 으로 변경
- Text 컴포넌트의 Alignment 를 Center, Middle 로 변경
- Color 필드 클릭 > 폰트 컬러를 하얀색(255, 255, 255) 로 변경
![](https://blog.kakaocdn.net/dn/dIQx73/btsMbXXa5ih/PMmV3IyWGNnAc529FkJ2Ek/img.png)
2. Time Text 의 폰트 크기 키우기
- Rect Transform 컴포넌트의 Pos Y 를 -30 으로 변경
- Text 컴포넌트의 Font Size 를 42로 변경
- Horizontal Overflow 와 Vertical Overflow 를 Overflow 로 변경
폰트 크기를 42로 증가시키면 글자가 글상자를 넘쳐서 잘리기 때문에 텍스트가 보이지 않게 된다. 이와 같이 표시할 글자 크기가 너무 크거나 표시할 글자 수가 너무 많으면 글이 글상자를 넘치게 된다.
텍스트 컴포넌트의 수평 오버플로(Horizontal Overflow) 와 수직 오버플로(Vertical Overflow) 는 글이 글상자를 넘칠 경우 해당 방향으로의 글자를 잘라낼 것인지 혹은 그대로 넘치게 표시할 것인지 결정한다.
Wrap 은 글자가 수평 방향으로 글상자를 넘칠 때 강제로 줄바꿈을 적용하고 Overflow 는 줄바꿈을 하지 않고 그대로 표시된다.
![](https://blog.kakaocdn.net/dn/b1u1hh/btsMa52PuPN/FApcBvgOrH8K1gQ7pqk1Jk/img.png)
3. 그림자 효과 추가
- Time Text 게임 오브젝트에 Shadow 컴포넌트 추가(Add Component > UI > Effects > Shadow)
![](https://blog.kakaocdn.net/dn/qmKp1/btsMcKJA6Ja/efyUVlOIxJkGpu2j1kOaX0/img.png)
8.3.4 게임오버 텍스트와 최고 기록 텍스트
이번에는 게임오버되었을 때 활성화할 UI 텍스트를 만든다. 게임 재시작 방법을 안내하는 텍스트와 최고 기록을 표시하는 텍스트를 제작한다. 직전에 완성한 Time Text 게임 오브젝트를 복제해서 재활용해서 만든다.
1. Gameover Text 만들기
- Time Text 선택 후 [Ctrl+D] 를 눌러 복제
- Time Text(1) 게임 오브젝트 이름을 Gameover Text 롤 변경
- Gameover Text 게임 오브젝트의 Text 컴포넌트의 Text 필드 값을 Press R to Restart 로 변경
![](https://blog.kakaocdn.net/dn/dyZcSB/btsMaOAcP39/s3TyUbHbfyMGNfluvNQAWK/img.png)
2. Gameover Text 를 화면 정중앙에 배치하기
- 앵커 프리셋 클릭 -> 앵커 프리셋 창이 나타남
- [Alt] 키를 누른 상태에서 middle-center 클릭
![](https://blog.kakaocdn.net/dn/H5fuA/btsMaOAcQTG/kKqEGjmQUKObkon8BWQiMk/img.png)
3. Record Text 만들기
- Gameover Text 게임 오브젝트 복제
- 이름을 Record Text 로 변경
- Rect Trasnform 컴포넌트의 Pos Y 를 -40 으로 변경
- Text 컴포넌트의 Text 필드 값을 Best Record : 0 으로 변경
- Text 컴포넌트의 Font Size 를 30 으로 변경
![](https://blog.kakaocdn.net/dn/eguVd1/btsMbrLfmSZ/Jx22hkQhoCiZkgWrPrvIJ0/img.png)
최고 기록 텍스트는 게임오버되었을 때 게임오버 텍스트와 함께 출력되어야 한다. 자식 게임 오브젝트는 부모 게임 오브젝트와 함께 활성화/비활성화된다.
따라서 게임 오버 텍스트에 최고 기록 텍스트를 넣어서 자식으로 만든다.
4. Record Text 를 Gameover Text 의 자식으로 만들기
- Record Text 를 Gameover Text 로 드래그&드롭
![](https://blog.kakaocdn.net/dn/dFAvqq/btsMctab8ky/vM5apHnWI1C54KosCsizL0/img.png)
5. Gameover Text 비활성화
- Gameover Text 의 체크 해제
![](https://blog.kakaocdn.net/dn/bUZpmb/btsMdmVWA4r/NABHSUxmHzrDpWvo0wCv01/img.png)
필요한 UI 게임 오브젝트를 모두 만들었다. 나중에 지금까지 완성한 UI 게임 오브젝트를 스크립트로 제어할 것이다.
UI 를 편집하기 쉽게 하기 위해 클릭했던 씬 창의 2D 버튼을 다시 클릭해서 2D 뷰를 해제한다. 그리고 씬을 저장하고 다음 과정으로 넘어간다.
8.4 게임 매니저 제작
게임의 규칙과 게임오버 상태를 표현하고, 생존 시간 등의 수치를 관리하고, 게임 UI 를 갱신하는 게임 매니저를 만든다.
8.4.1 GameManager 스크립트 준비
게임 매니저로서 동작할 GameManager 스크립트를 준비한다.
1. GameManager 스크립트 만들기
- 새 스크립트를 만들고 GameManager 로 이름 변경
![](https://blog.kakaocdn.net/dn/bIdclj/btsMaPZ9Llo/S7PPAxbvxxlksZqS2hDPE1/img.png)
2. 필요한 라이브러리 가져오기
using UnityEngine.UI; // UI 관련 라이브러리
using UnityEngine.SceneManagement; // 씬 관리 관련 라이브러리
가 추가되었다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // UI 관련 라이브러리
using UnityEngine.SceneManagement; // 씬 관리 관련 라이브러리
public class GameManager : MonoBehaviour
{
void Start()
{
}
void Update()
{
}
}
3. GameManager 에 필요한 변수와 메서드 선언하기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // UI 관련 라이브러리
using UnityEngine.SceneManagement; // 씬 관리 관련 라이브러리
public class GameManager : MonoBehaviour
{
public GameObject gameoverText; // 게임오버 시 활성화할 텍스트 게임 오브젝트
public Text timeText; // 생존 시간을 표시할 텍스트 컴포넌트
public Text recordText; // 최고 기록을 표시할 텍스트 컴포넌트
private float surviveTime; // 생존 시간
private bool isGameover; // 게임오버 상태
void Start()
{
// 생존 시간과 게임오버 상태 초기화
surviveTime = 0;
isGameover = false;
}
void Update()
{
}
// 현재 게임을 게임오버 상태로 변경하는 메서드
public void EndGame()
{
}
}
8.4.2 생존 시간 표시하기
이제 GameManager 스크립트에 생존 시간을 측정하고 표시하는 기능을 추가한다.
게임이 시작되고 몇 초 지났는지는 Update() 메서드에서 surviveTime 에 Time.deltaTime 값을 계속 더해서 누적함으로써 표현한다. 그다음 timeText 에 할당한 텍스트 컴포넌트의 Text 필드에 surviveTime 값을 이용해 생존 시간을 표시한다.
1. 생존 시간 표시하기
변수 timeText 에는 Time Text 게임 오브젝트를 할당할 것이기 때문에 timeText.text 는 인스펙터 창에서 편집했던 Time Text 게임 오브젝트의 텍스트 컴포넌트의 Text 필드라는 점에 주목한다.
(int)surviveTime 을 쓴 이유는 그냥 surviveTime 은 실수기때문에 소수점 아래 까지 나옴. 그냥 정수만 보이고 싶어서 (int) 로 형변환 해줬음.
이제 시간의 흐름에 따라 0, 1, 2, 3, 4, ... 이렇게 보일거임
void Update()
{
// 게임오버가 아닌 동안
if (!isGameover)
{
// 생존 시간 갱신
surviveTime += Time.deltaTime;
// 갱신한 생존 시간을 timeText 텍스트 컴포넌트를 이용해 표시
timeText.text = "Time: " + (int)surviveTime;
}
}
8.4.3 게임 재시작 구현
isGameover 가 true 라는 것은 게임오버된 상태라는 의미. 게임오버 상태에서는 특정 키를 눌러 게임을 재시작할 수 있어야 한다.
게임을 재시작한다는 것은 현재 씬을 다시 로드한다는 의미이다. 유니티에서 씬은 하나의 게임 월드이다. 현재 활성화된 씬을 해제하고 새로운 씬을 로드하는 방식으로 어떤 게임 월드에서 다른 게임 월드로 전환할 수 있다.
새로운 씬이 로드되면 기존 씬에 있던 모든 게임 오브젝트가 파괴된다. 이것을 응용하면 현재 활성화된 씬을 다시 로드하는 방식으로 게임 재시작을 구현할 수 있다.
GameManager 스크립트에 SampleScene 씬을 실시간으로 게임 도중에 로드하는 코드를 작성한다.
1. SampleScene 을 실시간으로 로드하기
void Update()
{
// 게임오버가 아닌 동안
if (!isGameover)
{
// 생존 시간 갱신
surviveTime += Time.deltaTime;
// 갱신한 생존 시간을 timeText 텍스트 컴포넌트를 이용해 표시
timeText.text = "Time: " + (int)surviveTime;
}
else
{
// 게임오버 상태에서 R 키를 누른 경우
if (Input.GetKeyDown(KeyCode.R)) {
// SampleScene 씬을 로드
SceneManager.LoadScene("SampleScene");
}
}
}
8.4.4 EndGame() 구현
마지막으로 GameManager 스크립트에 현재 게임을 게임오버 상태로 만드는 EndGame() 메서드를 구현한다. EndGame() 메서드는 플레이어가 죽을 때 실행되며, 현재 게임 상태를 게임오버 상태로 변경하고 게임오버 시 필요한 처리를 실행한다.
GameManager 스크립트에 구현된 EndGame() 메서드는 게임 매니저가 아니라 플레이어가 호출할 것이다. 플레이어가 죽었을 때 PlayerController 스크립트에서 GameManager 컴포넌트로 접근하여 EndGame() 메서드를 실행한다.
따라서 EndGame() 메서드는 외부에서 접근 가능하도록 public 으로 지정했다.
1. EndGame() 메서드 작성하기
isGameover 가 true 가 되면 Update() 메서드에서 생존 시간 surviveTime 이 더 이상 갱신되지 않는다.
// 현재 게임을 게임오버 상태로 변경하는 메서드
public void EndGame()
{
// 현재 상태를 게임오버 상태로 전환
isGameover = true;
// 게임오버 텍스트 게임 오브젝트를 활성화
gameoverText.SetActive(true);
}
8.4.5 PlayerPrefs
PlayerPrefs 는 Player Preference 라고 읽으며, 간단한 방식으로 어떤 수치를 로컬(프로그램을 실행 중인 현재 컴퓨터) 에 저장하고 나중에 다시 불러오는 메서드를 제공하는 유니티에 내장된 클래스이다.
PlayerPrefs 는 키-값 단위롤 데이터를 로컬에 저장한다. 값을 저장할 때 사용할 키가 무엇인지 기억하고 있다면 나중에 같은 키를 사용해 저장된 값을 다시 가져올 수 있다.
float 값을 저장할 땐 PlayerPrefs.SetFloat() 메서드를 사용한다. 입력으로 키와 키에 대응하는 값을 받는다. 이전에 저장된 값을 불러올 때는 PlayerPrefs.GetFloat() 메서드를 사용한다. 이 메서드는 입력으로 값을 저장하는 데 사용한 키를 받는다.
PlayerPrefs 의 Get 계열 메서드는 값을 가져올 때 주어진 키로 저장된 값이 존재하지 않으면 기본값을 반환한다. GetInt, GetFloat 은 0, GetString 은 빈 문자열 "" 을 사용한다.
8.4.6 최고 기록 저장/읽기 구현
GameManager 스크립트에서 작성한 EndGame() 메서드로 돌아가 최고 기록을 저장하고 읽는 부분을 추가한다.
1. GameManager 스크립트의 EndGame() 메서드 완성
// 현재 게임을 게임오버 상태로 변경하는 메서드
public void EndGame()
{
// 현재 상태를 게임오버 상태로 전환
isGameover = true;
// 게임오버 텍스트 게임 오브젝트를 활성화
gameoverText.SetActive(true);
// BestTime 키로 저장된 이전까지의 최고 기록 가져오기
float bestTime = PlayerPrefs.GetFloat("BestTime");
// 이전까지의 최고 기록보다 현재 생존 시간이 더 크다면
if (surviveTime > bestTime)
{
// 최고 기록 값을 현재 생존 시간 값으로 변경
bestTime = surviveTime;
// 변경된 최고 기록을 BestTime 키로 저장
PlayerPrefs.SetFloat("BestTime", bestTime);
}
// 최고 기록을 recordText 텍스트 컴포넌트를 이용해 표시
recordText.text = "Best Time: " + (int)bestTime;
}
8.4.7 완성된 GameManager 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // UI 관련 라이브러리
using UnityEngine.SceneManagement; // 씬 관리 관련 라이브러리
public class GameManager : MonoBehaviour
{
public GameObject gameoverText; // 게임오버 시 활성화할 텍스트 게임 오브젝트
public Text timeText; // 생존 시간을 표시할 텍스트 컴포넌트
public Text recordText; // 최고 기록을 표시할 텍스트 컴포넌트
private float surviveTime; // 생존 시간
private bool isGameover; // 게임오버 상태
void Start()
{
// 생존 시간과 게임오버 상태 초기화
surviveTime = 0;
isGameover = false;
}
void Update()
{
// 게임오버가 아닌 동안
if (!isGameover)
{
// 생존 시간 갱신
surviveTime += Time.deltaTime;
// 갱신한 생존 시간을 timeText 텍스트 컴포넌트를 이용해 표시
timeText.text = "Time: " + (int)surviveTime;
}
else
{
// 게임오버 상태에서 R 키를 누른 경우
if (Input.GetKeyDown(KeyCode.R)) {
// SampleScene 씬을 로드
SceneManager.LoadScene("SampleScene");
}
}
}
// 현재 게임을 게임오버 상태로 변경하는 메서드
public void EndGame()
{
// 현재 상태를 게임오버 상태로 전환
isGameover = true;
// 게임오버 텍스트 게임 오브젝트를 활성화
gameoverText.SetActive(true);
// BestTime 키로 저장된 이전까지의 최고 기록 가져오기
float bestTime = PlayerPrefs.GetFloat("BestTime");
// 이전까지의 최고 기록보다 현재 생존 시간이 더 크다면
if (surviveTime > bestTime)
{
// 최고 기록 값을 현재 생존 시간 값으로 변경
bestTime = surviveTime;
// 변경된 최고 기록을 BestTime 키로 저장
PlayerPrefs.SetFloat("BestTime", bestTime);
}
// 최고 기록을 recordText 텍스트 컴포넌트를 이용해 표시
recordText.text = "Best Time: " + (int)bestTime;
}
}
8.4.8 PlayerController 에서 EndGame() 실행
이제 PlayerController 스크립트를 편집해서 EndGame() 메서드를 실행한다.
PlayerController 스크립트에는 사망 시 실행되는 Die() 메서드가 있다. 그러므로 Die() 메서드에서 GameManager 스크립트의 EndGame() 메서드를 실행한다.
1. PlayerController 의 Die() 메서드 수정
public void Die()
{
// 자신의 게임 오브젝트를 비활성화
gameObject.SetActive(false);
// 씬에 존재하는 GameManager 타입의 오브젝트를 찾아서 가져오기
GameManager gameManager = FindObjectOfType<GameManager>();
// 가져온 GameManager 오브젝트의 EndGame() 메서드 실행
gameManager.EndGame();
}
8.4.9 게임 매니저 오브젝트 설정
이제 게임 매니저 역할을 할 Game Manager 게임 오브젝트를 만들고 GameManager 스크립트를 해당 게임 오브젝트에 추가한다.
1. GameManager 게임 오브젝트 만들기
- 빈 게임 오브젝트 생성 후 GameManager 로 이름 변경
- GameManager 스크립트 드래그&드롭
![](https://blog.kakaocdn.net/dn/baeBc8/btsMbZgkOWe/RncvC8SUc1RCMIeKQOSiP0/img.png)
2. GameManager 컴포넌트 설정
- Gameover Text 게임 오브젝트를 GameManager 컴포넌트의 Gameover Text 필드로 드래그&드롭
- Time Text 게임 오브젝트를 Time Text 필드로 드래그&드롭
- Record Text 게임 오브젝트를 Record Text 필드로 드래고&드롭
![](https://blog.kakaocdn.net/dn/OruTo/btsMbDxMkt1/W1sbLUBCWA6AymeZY0Qrj1/img.png)
8.5 빌드하기
완성된 유니티 프로젝트 닷지를 다른 사람에게 배포할 수 있는 형태로 빌드한다. 빌드하기 전에 내 문서나 바탕 화면 등의 경로에 빌드된 파일을 저장할 빈 폴더를 하나 만들어둔다.
1. 빌드를 저장할 폴더 만들기
- 바탕 화면이나 내 문서 등의 적당한 위치에 Dodge 라는 이름의 새 폴더 생성
2. 빌드하기
- 빌드 설정 창 열기(유니티 상단 메뉴의 File > Build Settings...)
- 빌드 설정 창에서 Build and Run 클릭 -> 파일 탐색기가 실행됨
- 파일 탐색기에서 준비한 Dodge 폴더를 찾아서 선택 > (설정 가능한 경우) 저장할 파일명을 Dodge 로 설정 > Save 클릭
![](https://blog.kakaocdn.net/dn/27WLI/btsMc06vPCH/7Y6q858DF98S58N1KNRlh1/img.png)
![](https://blog.kakaocdn.net/dn/bV2J6E/btsMbKjsbHQ/2AUckwgIQWOKIbbvc8tikK/img.png)
![](https://blog.kakaocdn.net/dn/uohDm/btsMa8SEn17/Sam8LWiReCyvYVJp4k6yNk/img.png)
8.6 마치며
첫 번째 예제인 닷지 게임을 완성했다.