Stage 내에서 공통적 기능 및 자원 관리에 필요한 LevelManager.cs 스크립트를 작성했다.
싱글톤 패턴으로 구현했다.
LevelManager.cs
using UnityEngine; using System.Collections; using UnityEngine.SceneManagement; using System; public class LevelManager : MonoBehaviour { //싱글톤 패턴. {get; private set;} = readonly public static LevelManager Instance { get; private set; } public string StageName { get; private set; } public string SongName; //스테이지 public int StageIdx { get; private set; } public int StageFPS; public bool IsGameStarted { get; set; } public bool IsPaused { get; private set; } public bool IsLevelClear { get; private set; } //점수 public bool HasNewRecord { get; set; } public float HighScore { get; set; } public float CurrScore { get; set; } public Player Player; private int _comboCnt; private int _comboArrIdx; private Color _yellow; private Color _grey; public GameObject[] ComboLblArr; //일시정지 팝업 public GameObject Pnl_Popup_Paused; public UILabel Paused_Lbl_Songname; public UILabel Paused_Txt_HighScore; //성공 팝업 public GameObject Pnl_Popup_Clear; public UILabel Clear_Lbl_Songname; public UILabel Clear_Lbl_HighScore; public UILabel Clear_Txt_HighScore; public UILabel Clear_Lbl_Score; public UILabel Clear_Txt_Score; public UILabel Clear_Lbl_NewRecord; //실패 팝업 public GameObject Pnl_Popup_Fail; public UILabel Fail_Lbl_Songname; public UILabel Fail_Lbl_HighScore; public UILabel Fail_Txt_HighScore; public UILabel Fail_Lbl_Score; public UILabel Fail_Txt_Score; public UILabel Fail_Lbl_NewRecord; //페이드 필터 public GameObject Pnl_FadeOut; //점수판정 public GameObject Pnl_Stage; public GameObject[] EvalQuotes; public Transform Evaluation; public Transform Pivot; public UILabel Lbl_Evaluation; public UILabel Lbl_CurrScore; //Bgm 관련 //Bgm for Android public int BgmID { get; private set; } private bool _isBgmLoaded; public string BgmFileName; //Bgm for StandAlone public AudioSource BgmAudio; public Transform Foreground; public void Awake() { Instance = this; //가비지 컬렉트 GC.Collect(); //인게임 프레임 고정 QualitySettings.vSyncCount = 0; Application.targetFrameRate = StageFPS; SaveData.LoadOption(); SaveData.LoadHiScore(); LoadBgm(); StageName = SceneManager.GetActiveScene().name; StageIdx = int.Parse(StageName.Substring(5, 2)); IsGameStarted = false; IsPaused = false; IsLevelClear = false; HasNewRecord = false; HighScore = SaveData.HiScore[StageIdx]; CurrScore = 0; _comboCnt = 0; _comboArrIdx = 0; _yellow = new Color(); ColorUtility.TryParseHtmlString("#FFEB06", out _yellow); _grey = new Color(); ColorUtility.TryParseHtmlString("#C8C8C8", out _grey); Paused_Lbl_Songname.text = SongName; Paused_Txt_HighScore.text = SaveData.HiScore[StageIdx].ToString(); Pnl_Popup_Paused.transform.localPosition = Vector3.zero; NGUITools.SetActive(Pnl_Popup_Paused, false); Fail_Lbl_Songname.text = SongName; Fail_Txt_HighScore.text = SaveData.HiScore[0].ToString(); Pnl_Popup_Fail.transform.localPosition = Vector3.zero; NGUITools.SetActive(Fail_Lbl_NewRecord.gameObject, false); NGUITools.SetActive(Pnl_Popup_Fail, false); Clear_Lbl_Songname.text = SongName; Clear_Txt_HighScore.text = SaveData.HiScore[StageIdx].ToString(); Pnl_Popup_Clear.transform.localPosition = Vector3.zero; NGUITools.SetActive(Clear_Lbl_NewRecord.gameObject, false); NGUITools.SetActive(Pnl_Popup_Clear, false); Pnl_FadeOut.transform.localPosition = Vector3.zero; NGUITools.SetActive(Pnl_FadeOut, false); NGUITools.SetActive(Lbl_Evaluation.gameObject, false); } public void Start() { //재생 및 싱크 처리 PlayBgm(); SetSync(); IsGameStarted = true; } public void FixedUpdate() { Evaluation.localPosition = new Vector3(-300, Pivot.position.y * 100, 0); } //플레이어 사망처리 public void KillPlayer() { StartCoroutine(KillPlayerCo()); } private IEnumerator KillPlayerCo() { Player.Kill(); StopBgm(); yield return new WaitForSeconds(2.0f); Time.timeScale = 0; if (SaveData.AutoRestartOnOff.Equals("ON")) { RestartStage(); } NGUITools.SetActive(Pnl_Popup_Fail, true); float fromScore = CurrScore - 60; while (fromScore < CurrScore) { fromScore++; Fail_Txt_Score.text = fromScore.ToString(); yield return null; } if (HasNewRecord) { HighScore = CurrScore; SaveData.HiScore[StageIdx] = (int)HighScore; SaveData.SaveHiScore(); NGUITools.SetActive(Fail_Lbl_NewRecord.gameObject, true); Fail_Lbl_Score.color = _yellow; Fail_Txt_Score.color = _yellow; Fail_Lbl_HighScore.color = _grey; Fail_Txt_HighScore.color = _grey; } } //어플리케이션 일시정지 시 public void OnApplicationPause(bool pause) { if (pause) { PauseGame(); } } //어플리케이션 종료 시 void OnApplicationQuit() { StopBgm(); ReleaseBgm(); } //게임 일시정지 public void PauseGame() { Debug.Log(this.name + " >>> PauseGame()"); if (IsLevelClear) return; IsPaused = true; PauseBgm(); Time.timeScale = 0; NGUITools.SetActive(Pnl_Popup_Paused, true); } //계속하기 public void ResumeGame() { Debug.Log(this.name + " >>> ResumeGame()"); if (!IsGameStarted) return; if (IsLevelClear) return; Time.timeScale = 1.0f; PlayBgm(); IsPaused = false; NGUITools.SetActive(Pnl_Popup_Paused, false); } //메인으로 돌아가기 public void ReturnToMain() { NGUITools.SetActive(Pnl_FadeOut, true); Time.timeScale = 1.0f; ReleaseBgm(); StartCoroutine(LoadMainScreenCo()); } IEnumerator LoadMainScreenCo() { AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(1); asyncOperation.allowSceneActivation = false; while (!asyncOperation.isDone) { while (asyncOperation.progress == 0.9f) { yield return new WaitForSeconds(0.5f); asyncOperation.allowSceneActivation = true; } yield return null; } } //스테이지 재시작 public void RestartStage() { NGUITools.SetActive(Pnl_FadeOut, true); Time.timeScale = 1.0f; ReleaseBgm(); StartCoroutine(LoadCurrScene()); } IEnumerator LoadCurrScene() { //Splash 0, Main 1이므로 각 stage의 index는 currStageIdx + 2 AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(StageIdx + 2); asyncOperation.allowSceneActivation = false; while (!asyncOperation.isDone) { while (asyncOperation.progress == 0.9f) { yield return new WaitForSeconds(0.5f); asyncOperation.allowSceneActivation = true; } } } //판정결과 및 점수처리 public void HandleEvaluationResult(int resultIdx, float points) { StartCoroutine(EvaluationResultCo(resultIdx, points)); } IEnumerator EvaluationResultCo(int resultIdx, float points) { //노트 판정에 따른 콤보처리 switch (resultIdx) { case 2: case 1: _comboCnt = 0; break; case 0: _comboCnt++; break; default: break; } UILabel lbl_ComboNum = ComboLblArr[_comboArrIdx].GetComponent<UILabel>(); if (_comboCnt > 0) { lbl_ComboNum.text = _comboCnt.ToString(); NGUITools.SetActive(lbl_ComboNum.gameObject, true); if (_comboArrIdx == 9) _comboArrIdx = 0; else _comboArrIdx++; } NGUITools.SetActive(EvalQuotes[resultIdx], true); CurrScore += points; float fromScore = CurrScore - 10.0f; while (fromScore < CurrScore) { fromScore++; Lbl_CurrScore.text = fromScore.ToString(); yield return null; } //최고점수 갱신여부 확인 if (CurrScore > HighScore) { if (!HasNewRecord) { Lbl_CurrScore.color = _yellow; HasNewRecord = true; } } yield return new WaitForSeconds(2.0f); NGUITools.SetActive(EvalQuotes[resultIdx], false); NGUITools.SetActive(lbl_ComboNum.gameObject, false); } //스테이지 클리어 처리 public void LevelClear() { StartCoroutine(LevelClearCo()); } IEnumerator LevelClearCo() { IsLevelClear = true; StopBgm(); GameObject resultLevel = Pnl_Popup_Clear.transform.Find("Img_Level").gameObject; TweenAlpha.Begin(resultLevel, 0.001f, 0.0f); NGUITools.SetActive(Pnl_Popup_Clear, true); float fromScore = CurrScore - 60; while (fromScore < CurrScore) { fromScore++; Clear_Txt_Score.text = fromScore.ToString(); yield return null; } if (HasNewRecord) { HighScore = CurrScore; SaveData.HiScore[StageIdx] = (int)HighScore; SaveData.SaveHiScore(); NGUITools.SetActive(Clear_Lbl_NewRecord.gameObject, true); Clear_Txt_Score.color = _yellow; Clear_Lbl_Score.color = _yellow; Clear_Txt_HighScore.color = _grey; Clear_Lbl_HighScore.color = _grey; } yield return new WaitForSeconds(0.4f); TweenPosition.Begin(resultLevel, 0.2f, new Vector2(290, -45)); TweenScale.Begin(resultLevel, 0.2f, new Vector3(1, 1, 1)); TweenAlpha.Begin(resultLevel, 0.2f, 1.0f); } //Bgm 로드 public void LoadBgm() { AndroidNativeAudio.makePool(); BgmFileName = "Android Native Audio/" + BgmFileName.Trim(); BgmID = ANAMusic.load(BgmFileName, false, true, BgmLoaded); ANAMusic.setPlayInBackground(BgmID, false); } //Bgm 로드여부 확인 public void BgmLoaded(int musicID) { _isBgmLoaded = true; } //Bgm 재생 public void PlayBgm() { if (Application.platform == RuntimePlatform.Android) { ANAMusic.play(BgmID); } else { BgmAudio.Play(); } } //Bgm 일시정지 public void PauseBgm() { if (Application.platform == RuntimePlatform.Android) { ANAMusic.pause(BgmID); } else { BgmAudio.Pause(); } } //Bgm 정지 public void StopBgm() { if (Application.platform == RuntimePlatform.Android) { ANAMusic.pause(BgmID); ANAMusic.seekTo(BgmID, 0); } else { BgmAudio.Stop(); } } //Bgm 메모리 해제 public void ReleaseBgm() { ANAMusic.release(BgmID); _isBgmLoaded = false; } //음악 - 스테이지 싱크 처리 public void SetSync() { StartCoroutine(SetSyncCo()); } IEnumerator SetSyncCo() { yield return new WaitForSeconds(2.0f); if (Application.platform == RuntimePlatform.Android) { Foreground.position = new Vector3((float)Math.Round(-((ANAMusic.getCurrentPosition(BgmID) / 1000.0f) * 12.8f), 3), Foreground.position.y, Foreground.position.z); } else { Foreground.position = new Vector3(((float)Math.Round(-(Math.Round(BgmAudio.time, 3) * 12.8f), 3)), Foreground.position.y, Foreground.position.z); } } }