본문 바로가기
카테고리 없음

[포트폴리오] LevelManager.cs 스크립트 작성하기

by 불타는홍당무 2017. 6. 13.

Stage 내에서 공통적 기능 및 자원 관리에 필요한 LevelManager.cs 스크립트를 작성했다. 

싱글톤 패턴으로 구현했다.


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);
        }
    }
}