본문 바로가기
Unity

게임 매니저, PlayerPrefs

by imagineer_jinny 2021. 7. 22.

* UI Canvas 만들기 (EventSystem은 지우기)

 

Canvas Scalar - Mode, Pixel Size 수정

Constant Pixel Size: 해상도가 아무리 변해도 UI 크기 변하지 않음, 해상도가 너무 크면  UI가 작게 보임

Scale With Screen Size: 기준 해상도에 맞춰 UI 배치하면 됨. 그 이후에 다른 해상도 나오면 유니티가 알아서 Scale Up, Down해줌, 그래서 UI 요소들이 흐릿하게 깨지는 일 발생하지 않음

 

Canvas의 자식으로 UI - Panel 추가후 Rect tool 사용해서 사이즈 조절

: 정보 띄워주는 용도 : Panel 이름 info Bar로 수정

 

info Bar 자식으로 text 2개 만들어주기 + info Bar에 Add Component로 Horizontal Layout Group 추가

Horizontal Layout Group: 나 자신의 자식들을 수평 방향으로 정렬해줌

옵션으로 Control Child Size가 있는데 자식들의 사이즈를 강제로 잡아늘리게 해줌: 글상자 여백을 다 채움.

Control Child Size도 체크해주기

 

Alignment , Best Fit

Best Fit: 글이 글상자에 맞춰서 자동으로 사이즈 지정

+폰트도 임포트해와서 수정 가능 

 

 

* 라운드 대기중인 패널 만들기

 

Canvas 오른쪽 - UI - Panel 

이름은 Round Ready Panel

 

Panel 자식으로 Text 만들어서 수정 

글 상자의 크기를 자기 자신의 부모 프레임에 맞춰 키워줌

 

이후 Round Ready Panel 꺼두기

 

 

* 라운드 구성

 

Play: 볼을 쏠 수 있고 쏘고 있는 상황.

볼이 어딘가에 닿아 폭발할때까진 영원히 안끝남.

 

End: 포신을 비롯한 조작용 컴포넌트들 꺼줌, 전체 컴포넌트 리셋

 

구현을 어떻게 해? 

코루틴과 무한루프!

 

 

빈 게임 오브젝트 GameManager 만들어주고 Add Component로 GameManager 스크립트도 만들어주기

 

player Preference는 유니티의 내장기능으로 키 값을 주고 어떤 값을 맡기면 나중에 키만 주면 그 값을 다시 가져올 수 있음. 게임이 끝난 뒤에도 그 값이 파일로 저장되어있어서 가져올 수 있음

 

값만 기억하고 있으면 키 값을 찾아가서 밸류를 가져올 수 있음, 다른 값으로 덮어쓰기도 가능 

미리 들어있는 키 값이 없으면 새로운 키, 밸류 만듦

 

GameManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
public class GameManager : MonoBehaviour
{

    public UnityEvent onReset;

    //싱글톤 위한 변수 만들어주자
    public static GameManager instance;

    public GameObject readyPanel;

    public Text scoreText;
    public Text bestScoreText;
    public Text messageText;

    public bool isRoundActive = false;
    private int score = 0;

    //현재 라운드의 페이지에 따라 끄거나 켜줄것임
    public ShooterRotator shooterRotator;

    public CamFollow cam;
    // Start is called before the first frame update
    void Awake()
    {
        //자기 자신을 싱글톤 자리에 넣어줌
        instance = this;
        UpdateUI();
    }

    void Start()
    {
        StartCoroutine("RoundRoutine");
    }
    //외부에서 점수 추가하고 빼기 위한 함수 
    public void AddScore(int newScore)
    {
        score += newScore;
        UpdateBestScore();
        UpdateUI();
    }

    //최고 점수를 기억하고 싶음, 게임을 껐다 켰을때도!
    //이 기능을 player preference를 통해 쓰고 싶음
    void UpdateBestScore()
    {
        //지금까지 player preference에 저장되어있는 점수보다 높으면 
        //score를 최고 스코어로 다시 player preference에 저장

        //player preference
        //값이 이미 있으면 덮어씌우고
        //없으면 새로만드는 코드

        if(GetBestScore() < score)
        {
            PlayerPrefs.SetInt("BestScore", score);
        }
      
    }

    //player preference에 저장되어있는 값을 가져오는 것임
    int GetBestScore()
    {
        int bestScore= PlayerPrefs.GetInt("BestScore");
        return bestScore;
    }

    void UpdateUI()
    {
        scoreText.text = "Score:" + score;
        bestScoreText.text = "Best Score: " + GetBestScore();
    }

    //Ball이 폭발할 때 자동으로 발생되는 함수 
    //Ball 친구가 게임 매니저로 들어가서 스스로 발동시킬것임

    public void OnBallDestroy()
    {
        UpdateUI();
        isRoundActive = false;

    }

    public void Reset()
    {
        score = 0;
        UpdateUI();

        //라운드를 다시 처음부터 시작
        StartCoroutine("RoundRoutine");
    }
        //코루틴 통해 만들것임

     IEnumerator RoundRoutine()
     {
        //READY
        onReset.Invoke();

            readyPanel.SetActive(true);
            cam.SetTarget(shooterRotator.transform, CamFollow.State.Idle);
            shooterRotator.enabled = false;
            isRoundActive = false;
            messageText.text = "Ready...";

            yield return new WaitForSeconds(3f);

            //PLAY
            //무한루프 사용
            isRoundActive = true;
            readyPanel.SetActive(false);
            shooterRotator.enabled = true;
            cam.SetTarget(shooterRotator.transform, CamFollow.State.Ready);
            
            while(isRoundActive==true)
            {
                yield return null;
            }

            //END

            readyPanel.SetActive(true);
            shooterRotator.enabled = false;

            messageText.text = "Wait For Next Round...";
            
            yield return new WaitForSeconds(3f);
            Reset();
     }
  }

 

할당해주기

 

Ball 스크립트로 돌아가서 파괴 코드 만져주기

 

OnTriggerEnter 함수 안에 코드 추가.

Ball이 OnTriggerEnter에 의해 파괴되는 순간 게임 매니저에게 나 자신이 파괴되었다고 전달하는 것(OnBallDestroy)

 

그럼 GameManager 스크립트에서 OnBallDestroy가 발동이 되서 isRoundActive를 false로 만들어서

무한루프 탈출

 

 

* Prop 점수처리 해주기

 

Prop.cs로 돌아가서 프롭은 자기가 파괴될 때 게임 매니저에게 점수 추가를 하고 죽어야 함

우리가 게임 매니저를 싱글톤으로 만들었기 때문에 게임 매니저를 일일이 레퍼런스로 가져올 필요 없이 싱글톤으로 바로 접근할 수 있음.

 

 

 

* 유니티 씬으로 돌아와서 Canvas 창에서 Canvas Scaler -Match : Width에서 Height로 당겨주기

지금 이 친구가 16:9의 화면인데 다른 비율의 화면에서는 어디를 고정으로 삼고 다른 축을 왜곡하냐는 뜻.

이걸 Width로 하면 가로 방향에 대해서는 왜곡이 안되는데 세로 방향에 대해서는 UI가 왜곡이 됨.

Height 쪽으로 옮겨주면 가로 방향에 대해서는 왜곡이 될 수 있지만 세로 방향에 대해서는 스크린 사이즈가 달라져도 왜곡이 안됨

 

* 몇 가지 추가사항

포탄을 쐈을 때는 카메라의 추적 대상이 포신이 아니라 포탄으로 옮겨갔으면 좋겠음. -> CamFollow

또 다음 라운드로 넘어갈 때 마다 매번 프롭이 리셋되면 좋겠음 -> SpawnGenerator

 

 

BallShooter 스크립트로 돌아가서

 

그 다음 매번 라운드 넘어갈 때 마다 SpawnGenerator가 리셋을 시켜줘야함

SpawnGenerator 스크립트 안에 Reset 함수가 있고 이걸 발동시키려고 하는데

GameManager에게 이벤트를 붙여줘서 만들어보려고 함.

 

GameManager.cs

 

ShooterPivot Reference 추가

'Unity' 카테고리의 다른 글

코루틴 WaitUntil  (0) 2021.08.05
오디오 믹싱 + 최종 빌드  (0) 2021.07.22
카메라 추적  (0) 2021.07.22
랜덤 오브젝트 생성기  (0) 2021.07.22
유니티에서 임포트패키지 밑에 여러 패키지들 안보일 때  (0) 2021.07.20

댓글