Ending the game
단순하지만 플레이 가능한 게임을 만들었습니다. 이제 소행성의 무한 루프에서 벗어나 소행성과 부딪혔을 때 게임을 끝내고 재시작 할것인지를 선택하도록 만들어야 할 것입니다.
두 개의 라벨이 필요합니다. 하나는 Game Over를 표시하는 용도이고, 다른 하나는 Restart를 묻는 용도입니다. Hierarchy를 체계적으로 구성하기 위해 먼저 DisplayText라는 빈 게임 오브젝트를 만들어서 기존의 Score Text와 새로 만들 두개의 라벨을 넣는 용도로 사용하겠습니다. Transform을 Reset하고 일단 Score Text를 드래그하여 DisplayText의 자식으로 만듭니다.
그리고 Score Text를 만들 때처럼 새로운 GUI text를 생성할 것입니다. Hierarchy창에서 Create>Create Empty하여 새 오브젝트를 생성한 뒤, 인스펙터 창에서 Add Component>Rendering>GUI text를 선택하여 추가합니다. 포지션을 0.5, 0.5, 0으로 조정하고 오브젝트 이름을 Restart Text, 역시 텍스트 내용도 Restart Text로 바꿔줍니다.
이제 가운데 화면에 Restart Text라는 글씨가 표시되었습니다.
이제 가운데 화면에 Restart Text라는 글씨가 표시되었습니다.
이제 이 글자를 우상단으로 옮기려고 합니다. 그래서 포지션을 1, 1, 0으로 지정해주면...화면에서 사라집니다. 우상방 가장 구석부터 글자가 시작되므로 안 나타나는게 당연합니다. 화면에 나타나게 하기 위해 포지션을 조절해줄 수도 있지만 그보다는 GUI Text 프로퍼티로 조절하는 것이 나을 것입니다.
프로퍼티에 Anchor라는 것이 있습니다. 기준점을 정하는 것인데 Upper Left로 되어 있는 것을 Upper Right로 바꿉니다. 그리고 Alignment를 Right로 해서 정렬을 바꿔줍니다. Offset은 -10,-10으로 해주면 모두 우상단에 여유를 두고 정렬되었습니다.
그리고, 텍스트를 Hierarchy상에서 드래그 하여 DisplayText의 자식으로 만듭니다.
같은 방식으로 또 하나의 GUI Text를 만들고 이름은 Game Over Text, 텍스트 내용도 Game Over Text로 지정합니다. Anchor는 Middle Center, Alignment는 Center로 합니다. 글씨를 중앙 살짝 상단에 위치시키기 위해 포지션은 0.5, 0.6, 0으로 합니다. 역시 드래그하여 DisplayText의 자식으로 만들어 줍니다.
다음으로 Game Controller의 스크립트를 수정해야 합니다.
방금 만든 GUI Text에 대한 레퍼런스를 작성합니다.
같은 방식으로 또 하나의 GUI Text를 만들고 이름은 Game Over Text, 텍스트 내용도 Game Over Text로 지정합니다. Anchor는 Middle Center, Alignment는 Center로 합니다. 글씨를 중앙 살짝 상단에 위치시키기 위해 포지션은 0.5, 0.6, 0으로 합니다. 역시 드래그하여 DisplayText의 자식으로 만들어 줍니다.
다음으로 Game Controller의 스크립트를 수정해야 합니다.
방금 만든 GUI Text에 대한 레퍼런스를 작성합니다.
public GUIText restartText;
public GUIText gameOverText;
| cs |
그리고 이 변수를 컨트롤 하기 위해 두개의 플래그를 세웁니다.
이 두개의 boolean 변수는 Start() 내에서 false로 일단 초기화됩니다. 마찬가지로 앞서 작성한 두개의 텍스트도 빈 문자열로 초기화됩니다.
private bool gameOver;
private bool restart;
| cs |
이 두개의 boolean 변수는 Start() 내에서 false로 일단 초기화됩니다. 마찬가지로 앞서 작성한 두개의 텍스트도 빈 문자열로 초기화됩니다.
private void Start()
{
gameOver = false;
restart = false;
scoreText.text = "";
gameOverText.text = "";
...
}
| cs |
이 변수들의 상태를 제어하기 위해 외부에서 접근가능한 메소드가 필요합니다.
인수는 필요치 않으며 내용도 아주 간단합니다. 그저 텍스트 내용과 플래그 상태만을 변화시킬 뿐입니다.
게임이 끝나면 무한루프를 빠져나올 방법이 필요합니다.
무한 루프 안에 gameOver가 true일때 빠져나올 코드를 만듭니다. 그리고 Update()메소드 내에서 R키가 눌렸는지를 판정하는 코드를 작성합니다.
restart를 하기 위해 R을 눌렀는지를 판정하고 애플리케이션을 다시 로드하는 코드입니다. obsolete으로 지정되었지만 아직 작동하는 코드입니다. 만일 새로운 방식으로 작성하려면
public void GameOver()
{
gameOverText.text = "Game Over";
gameOver = true;
}
| cs |
인수는 필요치 않으며 내용도 아주 간단합니다. 그저 텍스트 내용과 플래그 상태만을 변화시킬 뿐입니다.
게임이 끝나면 무한루프를 빠져나올 방법이 필요합니다.
IEnumerator SpawnWaves()
{
...
while (true)
{
...
if (gameOver)
{
restartText.text = "Press 'R' for Restart";
restart = true;
break;
}
}
}
| cs |
무한 루프 안에 gameOver가 true일때 빠져나올 코드를 만듭니다. 그리고 Update()메소드 내에서 R키가 눌렸는지를 판정하는 코드를 작성합니다.
private void Update()
{
if (restart)
{
if (Input.GetKeyDown(KeyCode.R))
{
Application.LoadLevel(Application.loadedLevel);
}
}
}
| cs |
restart를 하기 위해 R을 눌렀는지를 판정하고 애플리케이션을 다시 로드하는 코드입니다. obsolete으로 지정되었지만 아직 작동하는 코드입니다. 만일 새로운 방식으로 작성하려면
private void Update()
{
if (restart)
{
if (Input.GetKeyDown(KeyCode.R))
{
UnityEngine.SceneManagement.SceneManager.LoadScene
(UnityEngine.SceneManagement.SceneManager.GetActiveScene().name);
}
}
}
| cs |
와 같이 해야 합니다.
바뀐 전체 코드는 다음과 같습니다.
저장 후 유니티로 돌아갑니다. 새로 작성한 레퍼런스를 연결해 줍니다.
다음은 플레이어가 소행성과 부딪혀 파괴되었을 때 Game Over를 불러와야 합니다. 플레이어 게임오브젝트에서 감지하도록 할 수도 있지만 이미 다른 곳에 이 코드가 작성되어 있습니다. Asteroid 프리팹에 작성한 DestroyByContact가 바로 그것입니다. 에디터로 열어줍니다.
여기가 바로 소행성과 플레이어의 충돌을 감지하는 부분입니다. 여기의 가장 아래 부분에
을 넣어주면 되겠습니다.
전체 코드는 다음과 같습니다.
저장하고 유니티로 돌아갑니다. 씬을 저장한 뒤 플레이해보면
게임이 끝났을 때 메세지가 잘 출력되는 것을 확인할 수 있습니다.
글자 모양을 조금더 다듬어 보겠습니다.
Hierarchy창에서 Score Text와 Restart Text를 동시에 선택하고, 폰트 사이즈를 20으로 바꿉니다.
그리고 Game Over Text는 25로 해줍니다.
가시성이 훨씬 좋아졌습니다.
게임 제작이 끝났습니다. 이제 웹 플레이어를 빌드하여 배포하겠습니다.
File>Build Settings하여 세팅창을 엽니다.
세팅창은 크게 두 파트로 이루어집니다. 상단은 원하는 씬을 추가하는 곳이고, 하단은 빌드 대상을 선택하는 창입니다. 씬을 추가하는 방법은 직접 드래그하여도 되고, Add Open Scenes 버튼을 눌러도 됩니다.
씬을 추가했으면 하단의 Player Settings를 눌러 세부사항을 체크해보고, 문제 없으면 Build 버튼을 누릅니다. 위치를 묻는 창이 나오는데, 반드시 그럴 필요는 없지만 솔루션의 루트폴더에 Builds라는 새 폴더를 만든 후 안에 또 Space_Shooter 폴더를 만듭니다(영상에서는 빌드 이름을 지정하면 그것이 또 폴더로 만들어지던데 윈도우즈 환경이라 다른가봅니다). Space_Shooter를 지정하고 Save를 눌러 빌드합니다.
성공적으로 빌드가 끝났는데 index.html을 익스플로러, 크롬으로 실행해봐도 작동이 안 됩니다. 익스플로러는 지원하지 않는 것 같고, 크롬은 WebGL을 지원하긴 하나 local에서 실행하는 것은 보안상의 이유로 불가하다고 합니다. 서버에 올리면 작동 가능합니다. 또는 FireFox로 하면 되는 것 같은데 해보지는 않았습니다.
브라우저에서 실행되는 것까지 보고 싶었는데 좀 아쉽습니다. 어쩔수 없죠.
튜토리얼에는 랜덤으로 적이 나오는 확장판까지 있습니다만, 자막이 없어서 제 실력으로는 너무 힘드네요. 다른 게임 튜토리얼로 넘어가도록 하겠습니다.
바뀐 전체 코드는 다음과 같습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameController : MonoBehaviour
{
public GameObject hazard;
public Vector3 spawnValues;
public int hazardCount;
public float spawnWait;
public float startWait;
public float waveWait;
public GUIText scoreText;
public GUIText restartText;
public GUIText gameOverText;
private int score;
private bool gameOver;
private bool restart;
private void Start()
{
gameOver = false;
restart = false;
scoreText.text = "";
gameOverText.text = "";
score = 0;
UpdateScore();
StartCoroutine(SpawnWaves());
}
private void Update()
{
if (restart)
{
if (Input.GetKeyDown(KeyCode.R))
{
//Application.LoadLevel(Application.loadedLevel); 아래와 둘 중 선택
UnityEngine.SceneManagement.SceneManager.LoadScene
(UnityEngine.SceneManagement.SceneManager.GetActiveScene().name);
}
}
}
IEnumerator SpawnWaves()
{
yield return new WaitForSeconds(startWait);
while (true)
{
for (int count = 0; count < hazardCount; count++)
{
Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x),
spawnValues.y, spawnValues.z);
Quaternion spawnRotation = Quaternion.identity;
Instantiate(hazard, spawnPosition, spawnRotation);
yield return new WaitForSeconds(spawnWait);
}
yield return new WaitForSeconds(waveWait);
if (gameOver)
{
restartText.text = "Press 'R' for Restart";
restart = true;
break;
}
}
}
public void AddScore(int newScoreValue)
{
score += newScoreValue;
UpdateScore();
}
void UpdateScore()
{
scoreText.text = "Score: " + score;
}
public void GameOver()
{
gameOverText.text = "Game Over";
gameOver = true;
}
}
| cs |
저장 후 유니티로 돌아갑니다. 새로 작성한 레퍼런스를 연결해 줍니다.
다음은 플레이어가 소행성과 부딪혀 파괴되었을 때 Game Over를 불러와야 합니다. 플레이어 게임오브젝트에서 감지하도록 할 수도 있지만 이미 다른 곳에 이 코드가 작성되어 있습니다. Asteroid 프리팹에 작성한 DestroyByContact가 바로 그것입니다. 에디터로 열어줍니다.
if (other.tag == "Player")
{
...
}
| cs |
여기가 바로 소행성과 플레이어의 충돌을 감지하는 부분입니다. 여기의 가장 아래 부분에
gameController.GameOver();
| cs |
전체 코드는 다음과 같습니다.
public class DestroyByContact : MonoBehaviour
{
public GameObject explosion;
public GameObject playerExplosion;
public int scoreValue;
private GameController gameController;
private void Start()
{
GameObject gameControllerObject = GameObject.FindWithTag("GameController");
if (gameControllerObject != null)
{
gameController = gameControllerObject.GetComponent<GameController>();
}
else
{
Debug.Log("Cannot find 'GameController' script");
}
}
void OnTriggerEnter(Collider other)
{
if (other.tag == "Boundary")
return;
Instantiate(explosion, transform.position, transform.rotation);
if (other.tag == "Player")
{
Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
gameController.GameOver();
}
gameController.AddScore(scoreValue);
Destroy(other.gameObject);
Destroy(gameObject);
}
}gameController.GameOver();
| cs |
저장하고 유니티로 돌아갑니다. 씬을 저장한 뒤 플레이해보면
게임이 끝났을 때 메세지가 잘 출력되는 것을 확인할 수 있습니다.
글자 모양을 조금더 다듬어 보겠습니다.
Hierarchy창에서 Score Text와 Restart Text를 동시에 선택하고, 폰트 사이즈를 20으로 바꿉니다.
그리고 Game Over Text는 25로 해줍니다.
가시성이 훨씬 좋아졌습니다.
Building the game
게임 제작이 끝났습니다. 이제 웹 플레이어를 빌드하여 배포하겠습니다.
File>Build Settings하여 세팅창을 엽니다.
세팅창은 크게 두 파트로 이루어집니다. 상단은 원하는 씬을 추가하는 곳이고, 하단은 빌드 대상을 선택하는 창입니다. 씬을 추가하는 방법은 직접 드래그하여도 되고, Add Open Scenes 버튼을 눌러도 됩니다.
씬을 추가했으면 하단의 Player Settings를 눌러 세부사항을 체크해보고, 문제 없으면 Build 버튼을 누릅니다. 위치를 묻는 창이 나오는데, 반드시 그럴 필요는 없지만 솔루션의 루트폴더에 Builds라는 새 폴더를 만든 후 안에 또 Space_Shooter 폴더를 만듭니다(영상에서는 빌드 이름을 지정하면 그것이 또 폴더로 만들어지던데 윈도우즈 환경이라 다른가봅니다). Space_Shooter를 지정하고 Save를 눌러 빌드합니다.
성공적으로 빌드가 끝났는데 index.html을 익스플로러, 크롬으로 실행해봐도 작동이 안 됩니다. 익스플로러는 지원하지 않는 것 같고, 크롬은 WebGL을 지원하긴 하나 local에서 실행하는 것은 보안상의 이유로 불가하다고 합니다. 서버에 올리면 작동 가능합니다. 또는 FireFox로 하면 되는 것 같은데 해보지는 않았습니다.
브라우저에서 실행되는 것까지 보고 싶었는데 좀 아쉽습니다. 어쩔수 없죠.
튜토리얼에는 랜덤으로 적이 나오는 확장판까지 있습니다만, 자막이 없어서 제 실력으로는 너무 힘드네요. 다른 게임 튜토리얼로 넘어가도록 하겠습니다.
댓글 없음:
댓글 쓰기