Files
Travel_Run/Assets/Scripts/GameManager.cs
T
2026-06-22 09:19:19 +09:00

148 lines
4.8 KiB
C#

using UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;
// 게임 오버 상태를 표현하고, 게임 점수와 UI를 관리하는 게임 매니저
// 씬에는 단 하나의 게임 매니저만 존재할 수 있다.
public class GameManager : MonoBehaviour {
public static GameManager instance; // 싱글톤을 할당할 전역 변수
public bool isGameover = false; // 게임 오버 상태
public TextMeshProUGUI scoreText; // 점수를 출력할 UI 텍스트
public GameObject gameoverUI; // 게임 오버시 활성화 할 UI 게임 오브젝트
private int score = 0; // 게임 점수
private int currentLife; // 현재 남은 목숨
private int stageMileage = 0; // 현재 플레이 중 획득한 마일리지
private int totalMileage = 0; // 누적 보유 마일리지
public int maxLife = 3; // 시작 목숨
public int initialMileage = 500; // 첫 시작시 지급할 초기 마일리지
public bool grantInitialMileage = true; // 초기 마일리지 지급 여부
public bool saveMileageImmediately = true; // 스테이지 정산 전까지는 획득 즉시 누적한다.
private const string TotalMileageKey = "UniRun.TotalMileage";
private const string InitialMileageGrantedKey = "UniRun.InitialMileageGranted";
// 게임의 스피드를 올리는 변수
public float gameSpeed = 1f;
public float minGameSpeed = 1f;
public float speedIncreaseRate = 0.05f;
public float maxGameSpeed = 2f;
public float hitSpeedPenalty = 0.3f;
// 게임 시작과 동시에 싱글톤을 구성
void Awake() {
// 싱글톤 변수 instance가 비어있는가?
if (instance == null)
{
// instance가 비어있다면(null) 그곳에 자기 자신을 할당
instance = this;
}
else
{
// instance에 이미 다른 GameManager 오브젝트가 할당되어 있는 경우
// 씬에 두개 이상의 GameManager 오브젝트가 존재한다는 의미.
// 싱글톤 오브젝트는 하나만 존재해야 하므로 자신의 게임 오브젝트를 파괴
Debug.LogWarning("씬에 두개 이상의 게임 매니저가 존재합니다!");
Destroy(gameObject);
}
}
private void Start() {
currentLife = maxLife;
totalMileage = PlayerPrefs.GetInt(TotalMileageKey, 0);
if(grantInitialMileage && PlayerPrefs.GetInt(InitialMileageGrantedKey, 0) == 0)
{
totalMileage += initialMileage;
PlayerPrefs.SetInt(TotalMileageKey, totalMileage);
PlayerPrefs.SetInt(InitialMileageGrantedKey, 1);
PlayerPrefs.Save();
}
UpdateScoreUI();
}
void Update() {
// 게임 오버 상태에서 게임을 재시작할 수 있게 하는 처리
if(isGameover && Input.GetMouseButtonDown(0))
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
if (!isGameover)
{
// 게임 진행시 게임 속도는 시간에 따라 증가
gameSpeed += speedIncreaseRate * Time.deltaTime;
// 게임 최대 속도는 max를 넘어서지 못하게
gameSpeed = Mathf.Min(gameSpeed, maxGameSpeed);
UpdateScoreUI();
}
}
// 점수를 증가시키는 메서드
public void AddScore(int newScore) {
if(!isGameover)
{
score += newScore;
UpdateScoreUI();
}
}
// 마일리지 토큰을 먹었을 때 호출되는 메서드
public void AddMileage(int amount) {
if(isGameover)
{
return;
}
stageMileage += amount;
score += Mathf.Max(1, amount / 10);
if(saveMileageImmediately)
{
totalMileage += amount;
PlayerPrefs.SetInt(TotalMileageKey, totalMileage);
PlayerPrefs.Save();
}
UpdateScoreUI();
}
// 플레이어가 장애물에 부딪혔을 때 목숨과 속도를 줄이는 메서드
public bool TakeDamage(int damage = 1) {
if(isGameover)
{
return false;
}
currentLife -= damage;
currentLife = Mathf.Max(currentLife, 0);
gameSpeed -= hitSpeedPenalty;
gameSpeed = Mathf.Max(gameSpeed, minGameSpeed);
UpdateScoreUI();
return currentLife <= 0;
}
// 플레이어 캐릭터가 사망시 게임 오버를 실행하는 메서드
public void OnPlayerDead() {
isGameover = true;
gameoverUI.SetActive(true);
}
private void UpdateScoreUI() {
scoreText.text = "Score : " + score
+ "\nLife : " + currentLife + "/" + maxLife
+ "\nMileage : " + stageMileage
+ "\nTotal : " + totalMileage
+ "\nSpeed : " + gameSpeed.ToString("0.0");
}
}