티스토리 뷰
이제 마지막, 타이머를 만들어본다. 처음에 타이머를 만들 때, 타이머가 자꾸 초기화되는 현상이 나타났는데.. 별사탕 프리팹에 타이머가 초기화 되는 컴포넌트가 들어가곤 했었다. 참 버라이어티한 게임 만들기
Gamelog 21. 총알피하기 게임 만들기(5)
- 타이머
- 게임이 시작되면 타이머가 시작됨
- 캐릭터와 총알이 닿으면 타이머 시간이 멈춤
- 타이머 시간은 게임종료 화면으로 전달됨
- 게임종료화면에서는 최종 버틴 시간을 확인할 수 있음
- 다시시작 버튼을 누르면 게임시작 화면으로 넘어감
Gamelog 21_1. 게임이 시작되면 타이머가 시작되게 하기
먼저 타이머를 만들기 위해 Text
오브젝트를 생성한다.
UI > Legacy > Text를 통해 생성한다.
Legacy로 분류된 것이면, Text - TextMeshPro
를 활용해야 할 것 같지만.. 그건 다음에 해봐야겠다.
생성된 Text를 Timer
로 이름을 바꿔준다.
그리고 간단히 위치와 Text, Font Size, 정렬, Color 등을 변경해준다.
Layer는 자동으로 설정되었겠지만, UI
.
그리고 대망의 타이머.
이걸 넣으면 게임 같아지는 마법이 있다.
using System;
using UnityEngine;
using System.Diagnostics;
public class TimerManager : MonoBehaviour {
public static string Timer = @"00:00:00.000";
public bool IsPlaying;
public float TotalSeconds;
void Start() {
IsPlaying = true;
}
void Update() {
if (Time.timeScale == 0) {
IsPlaying = false;
}
if (IsPlaying) {
Timer = StopwatchTimer();
}
}
string StopwatchTimer() {
TotalSeconds += Time.deltaTime;
TimeSpan timespan = TimeSpan.FromSeconds(TotalSeconds);
string timer = string.Format("{0:00}:{1:00}:{2:00}.{3:00}",
timespan.Hours, timespan.Minutes, timespan.Seconds, timespan.Milliseconds);
return timer;
}
}
Time.deltaTime
을 통해서 시간이 흐르도록 해준다.Time.deltaTime
은 전 프레임이 완료되기까지 걸린 시간을 말한다. 컴퓨터의 성능이 느릴 수록 값이 커지며, 이를 이용하여 서로 다른 성능의 컴퓨터에서 같은 시간을 표시할 수 있다.
이를 이용하여 전체 초를 구하고, TimeSpan.FromSeconds
를 통해 전체 초를 밀리초 단위로 바꾼 후,시, 분, 초, 밀리초
로 타이머를 구성한다.
이걸 이렇게 Timer
오브젝트에 컴포넌트로 추가한다.
그렇게 되면, 내부적으로 타이머 값은 가지고 있지만 실제로 표시하는 로직은 없기에 타이머는 변하지 않는다.
이제 이 타이머를 움직이기 위해서는 표시하는 스크립트가 필요하다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
// 계속 카운터 값을 표시한다
public class Forever_ShowTimer : MonoBehaviour {
void Update() {
// 카운터 값을 표시한다
GetComponent<Text>().text = TimerManager.Timer;
}
}
GetComponent<Text>().text
의 값을 TimerManager.Timer
를 통해 얻은 값으로 변경해주면 타이머는 완성
타이머가 구동되었으며, 캐릭터와 총알이 닿으면 타임 자체가 멈추도록 해두었기 때문에
타이머도 같이 종료되게 된다.
Gamelog 21_2. 게임 종료시 게임 종료 화면 띄우기
이제 종료화면을 띄운다.
종료화면은 씬을 전환하면 조금 더 쉽지만, 게임 이용자 입장에서는 어느 장면에서 죽었는지 확인하기 어렵다는 피드백을 받아 씬을 전환하지 않고 바로 띄우도록 변형해본다.
Empty Object
를 생성하고 마지막 종료화면에서 배치할 게임타이틀, 게임오버문구, 리플레이 버튼을 배치한다.
그리고 모두 GameOver 오브젝트의 Child Object로 들어가도록 한다.
에러해결: NullReferenceException
NullReferenceException: Object reference not set to an instance of an object
OnCollision_Show.OnCollisionEnter2D (UnityEngine.Collision2D collision
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 충돌하면 표시한다
public class OnCollision_Show : MonoBehaviour {
public string targetTagName; // 목표 태그 이름 : Inspector에 지정
public string showObjectName; // 표시 오브젝트 이름 : Inspector에 지정
GameObject showObject;
void OnCollisionEnter2D(Collision2D collision) {
// 만약 충돌한 것의 이르이 목표 태그면
if (collision.gameObject.tag == targetTagName) {
showObject.SetActive(true); // 지웠던 것을 표시한다
}
}
}
그리고 캐릭터인 슬라임에게 충돌했을 경우, 해당 오브젝트를 보여주도록 스크립트를 적용한다.
위와 같은 스크립트를 적용하게 되면 GameObject.SetActive(false)
된 오브젝트를 찾을 수 없기 때문에
NullReferenceException 에러가 발생하게 된다.
따라서, 부딪히기 전에 해당 게임 오브젝트를 기억해두는 것이 필요하다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 충돌하면 표시한다
public class OnCollision_Show : MonoBehaviour {
public string targetTagName; // 목표 태그 이름 : Inspector에 지정
public string showObjectName; // 표시 오브젝트 이름 : Inspector에 지정
GameObject showObject;
void Start() {
// 지우기 전에 표시 오브젝트를 기억해 둔다
showObject = GameObject.Find(showObjectName);
showObject.SetActive(false); // 지운다
}
void OnCollisionEnter2D(Collision2D collision) {
// 만약 충돌한 것의 이르이 목표 태그면
if (collision.gameObject.tag == targetTagName)
{
showObject.SetActive(true); // 지웠던 것을 표시한다
}
}
}
Start()
시 GameObject.Find()
를 통해 사라질 게임오브젝트를 기억해둔 후에
나중에 부딪혔을 때 showObject.SetActive(true)
로 활성화시켜주는 것이 필요하다.
이제 태그를 가진 게임오브젝트와 충돌했을 때 부모 오브젝트를 숨기고 보여주고 하는 것이 가능하다.
(GameOver Object 에 SetActive(false)
를 넣어뒀다가 뺐는데, 안빠져있어서 왜 도대체 나타나지 않는 것인가 한참 찾아봤었다. 이런 식으로 삽질하는게 몇번짼지)
이제 이렇게 부딪히면 게임오버가 나타나는 것까지 완료되었다.
Gamelog 21_3. 다시시작 버튼 누르면 게임 시작 씬으로 전환하기
마지막 다시시작 버튼에 씬만 연결해주면 된다.
이건 초간단.! 시간이 지날수록 빨라지게 하는 난이도도 넣고 싶은데 너무 피곤하므로 일단 완성부터 하기로.
두번째 게시글에서 만들었던 OnMouseDown\_SwitchScene
을 Replay
버튼에 적용하고
전환할 첫번째 씬인 StartGame을 넣어주면 스크립트 끝!
Box Collider 2D 컴포넌트까지 넣어주면 완료
라고 생각했는데 리플레이를 누르니까 시간이 초기화가 안되고 게임이 중단되어 있는 문제가 확인되었다..
void Start() {
Time.timeScale = 1;
TotalSeconds = 0f;
IsPlaying = true;
}
유니티 타이머에서 조작하는 것이 명확한 역할이므로,TimerManager
에서 Time.timeScale
과 TotalSeconds
를 초기화 시켜주자.
정말 완성! 난이도 같이 더 업데이트할 내용이 있다면, 추후에 작성해보겠다.
유니티 총알 피하기 게임 만들기를 셀프로 진행해보았다.
총알은 아니고 행성피하기 게임이지만,!
'프로그래밍 > Unity' 카테고리의 다른 글
Gamelog 23. 미로찾기 게임 만들기(2) (2) | 2023.04.13 |
---|---|
Gamelog 22. 미로찾기 게임 만들기(1) (1) | 2023.04.12 |
Gamelog 20. 총알피하기 게임 만들기(4) (0) | 2023.04.03 |
Gamelog 19. 총알피하기 게임 만들기(3) (2) | 2023.03.26 |
Gamelog 18. 총알피하기 게임 만들기(2) (2) | 2023.03.22 |