안녕하세요. 인텔리원스튜디오(IntelliOneStudio)입니다.
이번 시간에는 Unity에서 타이머 기능을 구현하고, 시간이 흐름에 따라 UI를 업데이트하며, 타이머 종료 시 특정 이벤트를 발생시키는 방법을 알아보겠습니다. 특히 TimerManager 스크립트를 중심으로, 시간 표시, 일시 정지, 재개, 시간 추가, 그리고 애니메이션 제어 등을 구현하는 방법을 소개해 드릴게요.
이 스크립트를 통해 게임 내에서 시간 제한이 있는 레벨이나 미션을 효과적으로 관리할 수 있습니다. 단계별로 필요한 코드와 설명을 함께 제공하니, 프로젝트에서 바로 적용해 보세요.
2024.11.14 - [분류 전체보기] - [외워라!창고] 챗GPT를 활용해서 개발한 두 번째 게임을 여러분께 소개합니다!
창고에 물건을 보관하면 더이상 보여주지 않고, 오로지 당신의 기억력으로 찾아야해요.
날이 갈수록 늘어나는 상품들과 주문에도 정확하고 빠르게 물건을 찾아 배송해야해요.
과연 당신은 며칠까지 버틸수 있을까요?
당신의 기억력을 시험해봐요. 지금 다운로드하세요.
[아이폰 앱스토어 다운로드]
https://apps.apple.com/kr/app/%EC%99%B8%EC%9B%8C%EB%9D%BC%EC%B0%BD%EA%B3%A0/id6737766088
[구글 플레이 다운로드]
https://play.google.com/store/apps/details?id=com.intellione.warehousedelivery
저희가 챗GPT를 활용해서 개발한 첫 번째 게임을 여러분께 소개합니다! 이 게임은 챗GPT의 놀라운 AI 기능을 활용해 개발했어요. 즐거움이 가득한 이번 게임은, 챗GPT를 활용해서 누구든지 게임을 재미있게 만들 수 있다는 것을 보여줄 거에요.
* APP Store 에서 다운로드
https://apps.apple.com/kr/app/%EB%86%8D%EB%B6%80%EC%9D%98-%EA%BF%88/id6479183930
*Google Play 에서 다운로드
https://play.google.com/store/apps/details?id=com.intellione.farmersfirstdream&pcampaignid=web_share
주요 기능 소개
타이머 구현 및 UI 업데이트
- 남은 시간을 계산하여 UI 텍스트에 표시합니다.
- 특정 시간대에 따라 텍스트 색상과 표시 형식을 변경합니다.
타이머 일시 정지 및 재개
- 게임 이벤트에 따라 타이머를 일시 정지하거나 재개할 수 있습니다.
- 애니메이션의 재생 속도를 조절하여 시각적인 일치감을 줍니다.
시간 추가 및 애니메이션 효과
- DOTween을 사용하여 남은 시간을 부드럽게 증가시키는 애니메이션을 구현합니다.
씬 전환 시 타이머 리셋
- 특정 씬이 로드될 때 타이머를 리셋하여 새로운 레벨이나 미션에 대비합니다.
아래와 같이 ChatGPT에게 질문했어요.
※ ChatGPT 답변 내용 중 제가 별도로 표시한 굵은 글씨를 기준으로 읽으시면 좀 더 이해가 쉽게 될 거예요.
[질문]
안녕, ChatGPT. Unity에서 타이머를 구현하고, 시간이 흐름에 따라 UI를 업데이트하며, 타이머 종료 시 게임 오버를 처리하고 싶어. TimerManager 스크립트를 작성했는데, 어떻게 동작하는지 자세히 설명해 줄 수 있어?
[답변]
안녕하세요! TimerManager 스크립트를 통해 Unity에서 타이머를 구현하고, 시간에 따른 UI 업데이트 및 게임 오버 처리를 하는 방법을 단계별로 설명해 드릴게요.
1. 싱글턴 패턴을 통한 인스턴스 관리
public static TimerManager Instance { get; private set; }
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
설명:
- 싱글턴 패턴을 사용하여 TimerManager의 인스턴스를 전역에서 접근할 수 있도록 합니다.
- 이미 인스턴스가 존재하면 Destroy(gameObject)로 중복 생성을 방지합니다.
2. 타이머 초기화 및 시작
private void Start()
{
remainingTime = totalTime;
isTimerRunning = true;
UpdateTimerText();
UpdateDayText(); // 추가: Day 텍스트 업데이트
}
설명:
- remainingTime을 totalTime으로 초기화하고, 타이머를 실행 상태로 설정합니다.
- UpdateTimerText()와 UpdateDayText()를 호출하여 UI를 초기화합니다.
3. Day 텍스트 업데이트
private void UpdateDayText()
{
int selectedDay = PlayerPrefs.GetInt("SelectedDayIndex", 0);
dayText.text = $"Day {selectedDay + 1}";
}
설명:
- PlayerPrefs에서 선택된 Day 인덱스를 가져와 dayText에 표시합니다.
4. 타이머 업데이트 및 UI 반영
private void Update()
{
if (isTimerRunning && !isTimerPaused)
{
remainingTime -= Time.deltaTime;
if (remainingTime <= 0)
{
remainingTime = 0;
isTimerRunning = false;
TriggerGameOver();
}
UpdateTimerText();
}
}
설명:
- 매 프레임마다 남은 시간을 감소시키고, 시간이 0이 되면 게임 오버를 트리거합니다.
- UpdateTimerText()를 호출하여 UI에 남은 시간을 업데이트합니다.
5. 남은 시간에 따른 UI 효과
private void UpdateTimerText()
{
int minutes = Mathf.FloorToInt(remainingTime / 60);
int seconds = Mathf.FloorToInt(remainingTime % 60);
if (remainingTime <= 10f)
{
// 깜빡임 효과
timerText.color = Mathf.FloorToInt(remainingTime * 5) % 2 == 0 ? Color.red : Color.white;
timerText.text = $"{Mathf.FloorToInt(remainingTime)}";
}
else if (remainingTime <= 60f)
{
timerText.color = Color.yellow;
timerText.text = $"{Mathf.FloorToInt(remainingTime)}";
}
else
{
timerText.color = Color.white;
timerText.text = string.Format("{0}:{1:00}", minutes, seconds);
}
}
설명:
- 남은 시간이 10초 이하일 때는 텍스트 색상을 빨간색과 흰색으로 번갈아 표시하여 긴박감을 줍니다.
- 남은 시간이 1분 이하일 때는 텍스트 색상을 노란색으로 표시합니다.
- 그 외에는 기본 색상과 분:초 형식으로 시간을 표시합니다.
6. 게임 오버 처리 및 애니메이션 제어
private void TriggerGameOver()
{
if (LifeManager.Instance != null)
{
LifeManager.Instance.TriggerGameOver();
}
else
{
// Debug.LogError("LifeManager instance not found. Cannot trigger game over.");
}
if (targetAnimator != null)
{
targetAnimator.SetTrigger("StopAnimation");
}
}
설명:
- 남은 시간이 0이 되었을 때 게임 오버 이벤트를 발생시킵니다.
- targetAnimator에 StopAnimation 트리거를 설정하여 애니메이션을 멈춥니다.
7. 타이머 일시 정지 및 재개
public void PauseTimer()
{
isTimerPaused = true;
if (targetAnimator != null)
{
targetAnimator.speed = 0f;
}
}
public void ResumeTimer()
{
isTimerPaused = false;
if (targetAnimator != null)
{
targetAnimator.speed = 1f;
}
}
설명:
- 게임 이벤트에 따라 타이머를 일시 정지하거나 재개할 수 있습니다.
- 애니메이터의 속도를 조절하여 애니메이션도 함께 제어합니다.
8. 타이머 리셋 및 씬 전환 처리
private void OnEnable()
{
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDisable()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if (scene.name == "DaySceneName") // 데이 씬 이름을 여기에 기재
{
ResetTimer();
}
}
public void ResetTimer()
{
remainingTime = totalTime;
isTimerRunning = false;
isTimerPaused = false;
UpdateTimerText();
}
설명:
- 씬이 로드될 때 이벤트를 구독하여 특정 씬에서 타이머를 리셋합니다.
- OnSceneLoaded에서 씬 이름을 확인하고, 타이머를 초기화합니다.
9. 시간 추가 및 애니메이션 효과
public void AddTime(float timeToAdd)
{
float startValue = remainingTime;
float endValue = remainingTime + timeToAdd;
DOTween.To(() => remainingTime, x =>
{
remainingTime = x;
UpdateTimerText();
}, endValue, 0.5f)
.SetEase(Ease.OutQuad);
}
설명:
- DOTween을 사용하여 남은 시간을 부드럽게 증가시키는 애니메이션을 구현합니다.
- 시간이 증가하는 동안 UI도 실시간으로 업데이트됩니다.
전체 코드 예제
using UnityEngine;
using TMPro;
using WarehouseDeliveryQuest.UI;
using UnityEngine.SceneManagement;
using DG.Tweening;
namespace WarehouseDeliveryQuest.Managers
{
public class TimerManager : MonoBehaviour
{
public static TimerManager Instance { get; private set; }
public float totalTime = 239f;
public TextMeshProUGUI timerText;
public TextMeshProUGUI dayText; // Day를 표시하는 텍스트
public Animator targetAnimator; // 애니메이션 제어를 위한 Animator
private float remainingTime;
private bool isTimerRunning = false;
private bool isTimerPaused = false;
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
private void Start()
{
remainingTime = totalTime;
isTimerRunning = true;
UpdateTimerText();
UpdateDayText();
}
private void OnEnable()
{
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDisable()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
private void Update()
{
if (isTimerRunning && !isTimerPaused)
{
remainingTime -= Time.deltaTime;
if (remainingTime <= 0)
{
remainingTime = 0;
isTimerRunning = false;
TriggerGameOver();
}
UpdateTimerText();
}
}
private void UpdateTimerText()
{
int minutes = Mathf.FloorToInt(remainingTime / 60);
int seconds = Mathf.FloorToInt(remainingTime % 60);
if (remainingTime <= 10f)
{
timerText.color = Mathf.FloorToInt(remainingTime * 5) % 2 == 0 ? Color.red : Color.white;
timerText.text = $"{Mathf.FloorToInt(remainingTime)}";
}
else if (remainingTime <= 60f)
{
timerText.color = Color.yellow;
timerText.text = $"{Mathf.FloorToInt(remainingTime)}";
}
else
{
timerText.color = Color.white;
timerText.text = string.Format("{0}:{1:00}", minutes, seconds);
}
}
private void UpdateDayText()
{
int selectedDay = PlayerPrefs.GetInt("SelectedDayIndex", 0);
dayText.text = $"Day {selectedDay + 1}";
}
private void TriggerGameOver()
{
if (LifeManager.Instance != null)
{
LifeManager.Instance.TriggerGameOver();
}
else
{
Debug.LogError("LifeManager instance not found. Cannot trigger game over.");
}
if (targetAnimator != null)
{
targetAnimator.SetTrigger("StopAnimation");
}
}
public void PauseTimer()
{
isTimerPaused = true;
if (targetAnimator != null)
{
targetAnimator.speed = 0f;
}
}
public void ResumeTimer()
{
isTimerPaused = false;
if (targetAnimator != null)
{
targetAnimator.speed = 1f;
}
}
public void ResetTimer()
{
remainingTime = totalTime;
isTimerRunning = false;
isTimerPaused = false;
UpdateTimerText();
}
public float GetRemainingTime()
{
return remainingTime;
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if (scene.name == "DaySceneName") // 실제 씬 이름으로 변경하세요
{
ResetTimer();
}
}
public void AddTime(float timeToAdd)
{
float startValue = remainingTime;
float endValue = remainingTime + timeToAdd;
DOTween.To(() => remainingTime, x =>
{
remainingTime = x;
UpdateTimerText();
}, endValue, 0.5f)
.SetEase(Ease.OutQuad);
}
}
}
오늘은 TimerManager 스크립트를 활용하여 Unity에서 타이머를 구현하고, 시간에 따른 UI 업데이트와 게임 오버 처리, 그리고 애니메이션 제어까지 하는 방법을 알아봤어요.
이 시스템을 통해 게임 플레이에 긴박감을 주고, 플레이어에게 도전적인 요소를 제공할 수 있습니다.
지금까지 인텔리원스튜디오(IntelliOneStudio)였습니다!
감사합니다.
'디지털노마드' 카테고리의 다른 글
챗GPT 게임개발74: Unity에서 DOTween을 활용한 보상 젬 이동 연출하기 (3) | 2024.12.11 |
---|---|
챗GPT 게임개발73: Unity iOS Native Plugin으로 텍스트와 이미지 공유하기 (0) | 2024.12.11 |
챗GPT 게임개발71: Unity에서 Game Center 및 Google Play Games 리더보드 구현하기 (0) | 2024.12.03 |
챗GPT 게임개발70: Unity에서 다국어 지원과 언어별 폰트 적용하기 (4) | 2024.12.02 |
챗GPT 게임개발69: Unity에서 광고 쿨다운 시스템 구현하기 (1) | 2024.12.02 |