Unity

[Unity](빗방울 게임 마무리) 게임 끝내기

박도치 2023. 10. 27. 15:00

게임 끝내기에 앞서 Retry 판넬부터 만들어야 한다. 시간이 다 흐르면 판이 하나 등장하면서 다시하기 문구가 나오는 판넬을 만들어 볼 것이다.

 

 

1. Panel 꾸미기

  • image 사이즈: 400 / 250
  • txt 사이즈: 65
  • 글자 색상 (255, 255, 255, 255)
  • 배경 색상 (232, 52, 78, 255)
  • Inactive로 만들어두기

Canvas아래에 UI -> Panel을 만들어 그 아래에 UI -> Image 와 UI -> Text를 만들어 Image는 배경, Text는 다시하기 문구를 나타내 주면 된다.

 

여기서 Inactive로 만들어준다는 뜻은 게임 시작중에는 보이지 않다가 나중에 시간이 끝까지 흘러갔을 때 나타나야 하기 때문에 초기에는 보이지 않게 해줘야 한다. 이는 위에 체크표시를 해제해주면 된다.

체크 해제 전

.

2. Retry Panel 나타나게 하기

 

GameManager.cs에 이전에 Rain을 추가한것과 같이 GameObject를 추가하여 Panel을 띄우도록 해보자. Panel은 게임이 끝날 때 등장해야 하기 때문에 게임 끝났을 때의 로직에 추가해주도록 하자.

 

 

public GameObject panel;

void Update()
{
    limit -= Time.deltaTime;

    if (limit < 0)
    {
        limit = 0.0f;
        panel.SetActive(true);
        Time.timeScale = 0.0f;
    }

    timeText.text = limit.ToString("N2");
}

 

SetActive함수는 bool을 매개변수로 받는 함수이며 true일 때 해당 Object를 보여주게금 하는 Object제어 함수이다. 이를

true값으로 설정하면 게임이 끝날 때 panel이 보일것이다.

 

0.00초에 panel이 뜸

 

2. Retry Panel 버튼 부여하기

 

이제 Panel에 버튼을 부여하여 눌렀을 때 게임이 다시 시작할 수 있게끔 해주면 마무리가 된다.

 

먼저 Add Component에서 button을 검색하여 Component를 달아준다.

 

 

그리고 GameManager에서 Scene을 불러와야 하는데 이는 GameManager.cs에 해당 코드를 넣어주면 된다.

 

using UnityEngine.SceneManagement;

public void retry()
{
    SceneManager.LoadScene("MainScene");
}

 

이는 MainScene을 다시 Load해주는 역할을 하는데 retry에 넣어두면 retry가 될 때 MainScene이 Load되는 역할을 한다.

 

이제 Panel.cs를 추가하여 해당 코드를 넣어주자

 

Panel.cs

  public void retry()
    {
        GameManager.I.retry();
    }

 

마무리로 Onclick 이벤트를 부여주면되는데 이는 간단한게 이전에 button component에서 추가해 줄 수 있기 때문에 아래 사진과 같이 추가해주도록 하자.

 

사진에는 NoFunction이지만 탭을 누르고 Panel탭에 retry()를 선택해준다.

이러면 Panel 에 button onClick 이벤트가 부여가 된다.

 

 

그런데 실행해보면 문제가 하나 발생할것이다. 이는 다시하기를 누르고 시작했는데 시작이 안되는 현상일것이다. 왜냐하면 MainScene이 다시 Load가 됐을 때 초기화를 해줘야하는데 이를 하지 않았기 때문이다.

 

3. 초기화 해주기

 

초기화 해주기 위해서 함수를 생성한 후 start함수에 넣어주면 된다.

 

초기화 해야 할 대상은 멈춘시간(timeScale)을 1로 해주고,점수(totalScore)를 초기화 해주며, 시간(limit)도 초기화 해줘야 한다.

 

아래 limit은 편의를 위해 잠시 5로 정해놨다.

void Start()
    {
        initGame();
        // 0.5초 마다 makeRain 함수를 호출한다.
        InvokeRepeating("makeRain", 0, 1f);
    }

void initGame()
    {
        Time.timeScale = 1.0f;
        totalScore = 0;
        limit = 5f;
    }

 

 

4. 결과물

 

완성된 결과는 다음과 같다. 테스팅하기위해 5초로 설정해뒀지만 60초로 바꿔주면 된다.

 

 

코드

 

GameManager.cs

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{

    public GameObject rain;
    public GameObject panel;

    public static GameManager I;

    public Text scoreText;
    public Text timeText;

    // 제한 시간
    float limit = 60.0f;
    int totalScore = 0;

    void Awake()
    {
        I = this;
    }
    // Start is called before the first frame update
    void Start()
    {
        initGame();
        // 0.5초 마다 makeRain 함수를 호출한다.
        InvokeRepeating("makeRain", 0, 1f);
    }

    // Update is called once per frame
    void Update()
    {
        limit -= Time.deltaTime;
       
        // 0초가 될 시에 게임이 멈춤
        if(limit < 0)
        {
            // timeScale 시간을 멈출지 빠르게 느리게할지 정해주는 역할
            Time.timeScale = 0.0f;
            limit = 0.0f;
            panel.SetActive(true);
        }
        // N2 => 소수점 두자리까지 체크
        timeText.text = limit.ToString("N2");
    }

    void makeRain()
    {
        Instantiate(rain);
        //Debug.Log("비가 내린다!");
    }

    public void addScore(int score)
    {
        totalScore += score;
        scoreText.text = totalScore.ToString();
        //Debug.Log(totalScore);
    }

    //retry panel에만 넣어도 되는데 왜 Gamemanager.cs에 retry를 넣었는가?
    // >>> panel뿐만 아니라 후에 다른 요소에서도 retry를 불러 올 수 있기 때문에 gameManager에 넣어둔다.
    public void retry()
    {
        SceneManager.LoadScene("MainScene");
    }

    void initGame()
    {
        Time.timeScale = 1.0f;
        totalScore = 0;
        limit = 60.0f;
    }
}

 

Panel.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Panel : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
       
    }

    public void retry()
    {
        GameManager.I.retry();
    }
}

 

Rain.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Rain : MonoBehaviour
{
    int type;
    float size;
    int score;
    // Start is called before the first frame update
    void Start()
    {
        float x = Random.Range(-2.7f, 2.7f);
        float y = Random.Range(3.0f, 5.0f);
        transform.position = new Vector3(x, y, 0);

        type = Random.Range(1, 5);

        if (type == 1)
        {
            size = 1.2f;
            score = 3;
            // GetComponent<SpriteRenderer>() 는 C#에서 SpriteRenderer를 제어하는 함수,
            GetComponent<SpriteRenderer>().color = new Color(100 / 255f, 100 / 255f, 100 / 255f, 100 / 255f);
        }
        else if (type == 2)
        {
            size = 1.2f;
            score = 2;
            GetComponent<SpriteRenderer>().color = new Color(130 / 255f, 130 / 255f, 130 / 255f, 255 / 255f);
        }
        else if(type == 3)
        {
            size = 0.8f;
            score = 1;
            GetComponent<SpriteRenderer>().color = new Color(150 / 255f, 150 / 255f, 255 / 255f, 255 / 255f);
        }
        else
        {
            size = 0.8f;
            score = -5;
            GetComponent<SpriteRenderer>().color = new Color(255 / 255.0f, 100.0f / 255.0f, 100.0f / 255.0f, 255.0f / 255.0f);
        }

        transform.localScale = new Vector3(size, size, 0);
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    void OnCollisionEnter2D(Collision2D coll)
    {
        if (coll.gameObject.tag == "Ground")
        {
            Destroy(gameObject);
        }
        if (coll.gameObject.tag == "Rtan")
        {
            Destroy(gameObject);
            GameManager.I.addScore(score);
        }
    }

}

 

Rtan.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Rtan : MonoBehaviour
{
    float direction = 0.05f;
    float toward = 1.0f;
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            toward *= -1;
            direction *= -1;
        }
        if (transform.position.x > 2.8f)
        {
            direction = -0.05f;
            toward = -1.0f;
        }
        else if (transform.position.x < -2.8f)
        {
            direction = 0.05f;
            toward = 1.0f;
        }

        transform.localScale = new Vector3(toward, 1, 1);
        // Debug.Log(transform.position.x);
    }
    void FixedUpdate()
    {
        transform.position += new Vector3(direction, 0, 0);
    }
}

 

끝!