본문 바로가기
tips/유니티 게임만들기

유니티 강좌 8 - 총알 피하기 8/9. 시간계산과 Text 출력

by 디지털 수공업자 2021. 3. 26.
반응형

 

1. 게임 시작 후에 총알 생성

총알은 GameController.csStart( )에서 MakeBullet( )을 호출하여 만들어진다. 7편에서 게임 시작 UI를 넣었기 때문에, 이제는 Start( )에서 자동으로 시작되지 않고, 게임 시작 버튼을 누르면 총알이 생성되기 시작하도록 바꾸어주자.

 

Start( )에 있던 반복호출문을 PressStart( ) 안으로 옴기면, 하려던 작업은 끝이 난다.

유니티 에디터에서 플레이를 시키고 Hierarchy에 있는 uiStart의 인스펙터에서 비활성화를 시켜보자. 게임이 실행된 상태이지만 총알이 생성되지 않고 있다. 다시 인스펙터에서 uiStart를 활성화 시키고 시작 버튼을 눌러보자. 그 때 부터 총알이 만들어지는게 보이면 순조롭게 잘 작동 되는 것이다.

 

2. 플레이 시간 UI

uiStart가 화면을 가리고 있어 작업하기가 어려우므로 인스펙터에서 비활성화를 시키고, GameObject > UI > Text 에서 Text 게임 오브젝트를 생성한다. 게임오브젝트에 등록되어 있는 Text 콤포넌트는 화면에 글씨를 표현해주는 기능을 하며 Canvas안에서만 작동한다. Text 게임오브젝트가 Hierarchy에서 Canvas밖에 있으면 화면에 아무런 글씨도 보이지 않게된다. 이는 GameObject > UI 안에서 생성하는 모든 게임오브젝트들 모두 동일하다. 

생성된 게임오브젝트의 이름을 uiTime으로 변경한다. RectTransformAnchor Preset에서 가로기준은 center, 세로기준은 top으로 변경하고 x, y, width, height 값을 위와 같이 입력한다. 세로기준을 top으로 하면 Canvas의 윗변을 기준으로 위치시켜 다양한 가로세로 비율의 기기에서 보여지더라도 항상 비슷한 비율로 화면의 위쪽에 보여진다. Game창의 해상도 설정을 바꿔보며 어떻게 나타나는지 확인해보자.

Text에 TIME 문자열을 입력하고, Font Size에 80을 입력한다.
ParagraphRectTransform에서 지정한 게임오브젝트의 가로 세로 크기 영역안에 문자를 어디에 위치시킬지 정렬하는 옵션이다. Alignment의 오른쪽에 버튼 세 개씩 묶인 두 그룹이 있는데, 왼쪽 그룹은 가로 정렬로 왼쪽, 중앙, 오른쪽을 선택할 수 있고, 오른쪽 그룹은 세로 정렬로 위, 중간, 아래를 선택할 수 있다. 여기에서는 가로, 세로 모두 중앙으로 설정한다.

 

3. 시간 출력

게임을 시작하고 생존해 있는 시간을 계산하여 위에서 만든 uiTime에 보여주려 한다. GameController.cs에 새로운 int형 변수 sec를 선언한다. 이 변수는 GameController.cs 내부에서만 사용하므로 public을 앞에 붙이지 않아도 무방하다. 물론 붙여도 상관은 없다...

방금 선언한 sec 변수의 값을 PressStart 안에서 0으로 대입해준다. 게임을 시작하려고 시작 버튼을 누르면 sec의 값은 항상 0이 되는 것.
위에서 변수가 참조되는 범위를 살펴볼 수 있게 추가로 int형 min변수를 Start( )안에서 선언해보았다. sec 변수와 min 변수는 선언한 위치가 차이가 나는데, 함수 안에서 선언된 변수는 오로지 그 함수 안에서만 접근할 수 있다. 따라서 PressStart에서 min에 값을 대입하려하면 오류가 발생한다. 오로지 그 함수안에서만 써도 되는 변수라면 함수안에서 선언하면 되며 이를 지역변수라고 하고, 여러 함수에서 두루 써야하는 변수라면 sec와 같이 함수 밖 클래스 안에 선언하며 이를 전역변수라고 한다. min변수는 설명을 위해 적은 것이므로 삭제한다.

이 시리즈의 처음에 C# 문장형식의 공통점을 비유로 설명했었는데, 이 전역변수의 경우도 소괄호와 중괄호만 없을 뿐 다른 함수와 동일한 깊이에 동일한 형식으로 작성되고 있음을 공통점으로 발견해보자.

변수 sec를 uiTime 게임오브젝트의 Text콤포넌트에 전달을 해야하므로 스크립트에 uiTime의 Text 콤포넌트를 연결해야 한다. 이제껏 GameObject형 변수를 만들어 GameObject를 연결시켰던것과 동일한 방법으로 Text형 변수 uiText를 public 으로 선언하고, 인스펙터에서 uiTime 게임오브젝트를 드래그하여 연결한다.

유니티에서 Text콤포넌트를 스크립트에서 다루려면 using UnityEngine.UI 를 추가해 주어야 한다. 유니티에서 스크립트 파일을 생성하면 항상 기본으로 입력되어 있는 문장들 중에 최상단에는 using XXXX 와 같은 문장이 세 개가 있다. 우리가 지금까지 호출했던 많은 함수들이 어딘가에는 정의되어 있기 때문에 호출하는대로 작동을 했던 것인데, 그 어딘가에 있는 함수의 정의를 연결시켜주는 것이 이 부분이다. 자세한 것은 차후에 살펴보기로 하며 Text콤포넌트를 사용하려면 UnityEngine.UI연결해주어야 한다는 점만 기억하자.

GameController 콤포넌트에 위와 같이 등록되었으면 OK

SetTime( ) 함수를 만들고 변수값을 대입해준다.
Text형 uiTime에 uiTime게임오브젝트의 Text콤포넌트가 연결된 상태 이므로 스크립트에서 uiTime변수는 Text콤포넌트와 마찬가지이다. 여기에 .text를 사용하면 Text콤포넌트의 text변수에 접근할 수 있다. Text콤포넌트의 text변수는 자료형이 문자열이기 때문에 문자열 값을 넣어주어야 하는데 sec는 int형 값이기 때문에 uiTime.text = sec ; 와 같이 대입하면 오류가 발생한다. 숫자를 문자열로 바꾸어 주는 함수 ToString( )를 뒤에 사용하여 sec의 값을 문자열로 바꾸어 대입해줄 수 있다.


또 다른 간단한 방법도 있다. C#에서는 문자열 + 숫자를 연산하면 숫자를 문자열로 변환하여 문자열과 합쳐준다. 와와 같이 큰따옴표 사이를 띄우지 않은 아무것도 없는 문자열을 sec에 더해주면 int형 숫자가 string형 문자열로 변환된다. sec의 값이 만약 5인데 빈문자열을 더해주면 결과는 5라는 문자가 된다. 이는 숫자가 아니기 때문에 다시 여기에 3이라는 int값을 더해주면 결과는 8이되지 않고 53이라는 문자열이 된다.

이제 SetTime( ) 함수를 호출하면 게임화면 상단에 sec의 값이 보이게 된다.

예전에 총알 반복 생성에 사용했던 InvokeRepeating( )을 한번 더 쓰자. 게임 시작을 누르면 1초 뒤부터 1초마다 SetTime( )를 반복 호출한다. 그리고 SetTime( )이 호출되면 uiTime에 sec변수를 보여주기 전에 숫자 1을 더해준다. SetTime( )이 호출될 때 마다 sec변수의 값은 1씩 증가하고 화면에 그 값을 보여주게 된다.

 

 

4. 게임오버

uiStart를 만들었던 것과 같은 방법으로 uiEnd를 만든다. 그 안에는 Text를 하나 만들어 화면 가운데에 큼지막하게 GAME OVER라고 표시한다. uiStart를 게임이 시작되면 비활성화 시켰던 것과 반대로 uiEnd는 처음에 비활성화를 시켜두고 player가 총알을 만나면 활성화시켜 게임이 끝났음을 보여준다.

GameController.cs에 GameObject형 변수를 만들어 uiEnd 게임오브젝트를 연결해준다. 

다시 Player.cs에서 총알을 만났을 때 발동되는 이벤트를 보자.
이 시리즈 앞 부분에서 등장했던 GameObject.Find(게임오브젝트이름)로 게임오브젝트를 찾은 다음 transform콤포넌트의 position변수에 접근했던 것과 같은 방법으로, "game"이라는 이름의 게임오브젝트를 찾은 다음 GetComponent( ) 라는 함수로 GameController콤포넌트에 접근하고 다시 그 안에 있는 GameObject형 uiGameObjectObject 변수에 접근하여 SetActive( )함수로 활성화를 시켜준다.

길어서 복잡하지만 마침표를 "~의"라고 생각해보면 크게어렵지 않다. "game"이름 오브젝트의 GameController 콤포넌트의 uiEndGameObject의 SetActive( )함수에 true값 주기.

단 여기서 지금까지 본적없는 GetComponent<콤포넌트이름>( ) 와 같은 문장형태가 등장한다. 꺽쇠가 들어가는 함수를 일반함수라고 하며 꺽쇠안에는 형식매개변수라고하여 GetComponent가 반환해줄 자료형을 정하는 형식이 된다. 아무튼 GetComponent<>( )를 사용하면 꺽쇠안에 넣어준 이름의 콤포넌트를 얻어올 수 있다.

당연히 "game"이름의 게임오브젝트에서 얻어온 GameController콤포넌트는 지금까지 우리가 작성해왔던 GameController.cs 이다.

게임이 시작된 후에 player가 총알을 만나면 uiEnd가 활성화되어 게임오버 글씨가 출력된다.


여기까지 완성된 스크립트 파일 입니다.

Player.cs
0.00MB
GameController.cs
0.00MB


5. 정리

게임오버된 후에 다시 게임을 초기화하고 시작할 수 있도록 만들려면 몇 가지 해야할 일이 더 남아있다. 게임오버 화면에 다시시작하기 버튼을 넣어주고, 그 버튼을 눌러 게임이 시작될 때에는 씬안에 있는 모든 총알을 즉시 파괴하고, 화면 상단에 보이는 시간을 0으로 만들어 주어야 한다. 다음 9편에서 이 부분을 만들고 안드로이드 폰에서 테스트를 해보자.

내용이 도움되셨다면 구독 & 공감 부탁드립니다.
시리즈가 계속되는 힘이 됩니다.


GameObject.GetComponent( ) : docs.unity3d.com/kr/530/ScriptReference/GameObject.GetComponent.html

 

유니티 강좌 9 - 총알 피하기 9/9. 태그와 배열, 안드로이드 빌드

아래 내용은 8편에서 이어집니다. 1편 : boxwitch.tistory.com/180 8편 : boxwitch.tistory.com/197 다시 시작하기 UI uiEnd 안에 Button 게임오브젝트를 생성하고 이름을 btnRestart로 변경하여 적당히 위치를..

boxwitch.tistory.com

 

반응형

댓글