-
[Unity 2D] Fly Bird 스코어 누적 count 하기 (+ 간단 버그 수정)Unity 2D 2023. 3. 25. 21:49
저번 글에서 Bird가 파이프에 부딪히면 동작을 멈추도록 했다.
이번에는 Bird가 파이프를 통과할 때 1점씩 점수를 획득하도록 만들어보자 ..
그 전에 저번 글에서 Bird가 멈추게 했는데, 정작 파이프 반복 생성을 막는 걸 놓쳤었다.
그리고 오류 한 가지 또 놓침 ㅠㅠ
Bird가 초반 Ready 상태일 때도 파이프가 계속 생성되고 있다.
그거 먼저 잡고 가야겠다..,
아주 간단하다. (간단한 걸 놓쳐버림~)
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SpawnPoint : MonoBehaviour { // 파이프 프리팹 public GameObject pipePrefab; // 스폰 시간 [SerializeField] float spawnTime = 1; // 타이머 private float countdown = 0; // 랜덤하게 나올 스폰 타임 [SerializeField] float spawnMaxTime = 1.1f; [SerializeField] float spawnMinTime = 0.9f; // 랜덤하게 나올 스폰 위치 [SerializeField] float spawnMaxY = 2.3f; [SerializeField] float spawnMinY = -1.3f; void Update() { // Death 상태이거나 Start 전이면 프리팹 생성을 멈춘다 if(GameManager.isStart == false || GameManager.isDeath == true) { return; } // 타이머 구현 countdown += Time.deltaTime; if (countdown >= spawnTime) { SpawnPipe(); countdown = 0; // 시간을 랜덤하게 스폰하기 spawnTime = Random.Range(spawnMinTime, spawnMaxTime); } } void SpawnPipe() { // 위치를 랜덤하게 스폰하기 float spawnY = transform.position.y + Random.Range(spawnMinY, spawnMaxY); Vector3 randomPosition = new Vector3(transform.position.x, spawnY, transform.position.z); // 파이프 프리팹 생성 Instantiate(pipePrefab, randomPosition, Quaternion.identity); } }
그냥 조건에 맞게 return 시켜주면 된다.
Ready 상태에서는 파이프가 생성되지 않는 걸 확인할 수 있다. 게임이 끝났을 때 파이프가 생성되지 않는 걸 확인할 수 있다. 이제 파이프를 통과할 때 1점씩 얻을 수 있도록 스코어를 누적시키자.
UI를 활용해서 만들 예정이다.
이 게임의 UI를 관리할 캔버스를 생성할 것이다.
(모든 UI가 화면에 나타나기 위해서는 무조건 캔버스에서 나타내야 한다.)
하이라키창에서 우클릭 → UI → Canvas 클릭
빈 오브젝트로 PlayUI 라고 UI 폴더를 따로 나눴다.
(나중에 안 헷갈리기 위해서 미리미리 폴더를 정리하자.)
숫자를 입력하기 위해서 TextMeshPro를 사용한다.
하이라키창 우클릭 → UI → Text - TextMeshPro 클릭
텍스트의 위치를 설정할 수 있다. 텍스트에 다양한 효과를 줄 수 있다. 개인적으로 UI는 결국 개인 센스 감각에 따라 달라진라고 생각한다.물론 어느 정도 스킬과 지식은 당연히 가지고 있어야 하지만.. ^_ㅠ나도 일단 대충 꾸며보았다... . .. . ..
위 숫자 00는 누적될 스코어가 보여질 곳이다.
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GameManager : MonoBehaviour { // 플레이어 죽음 체크하기 public static bool isDeath = false; // 플레이어 시작 체크하기 public static bool isStart = false; // 스코어 public static int score = 0; void Start() { isDeath = false; isStart = false; score = 0; } }
GameManager에서는 보통 score, life, bool 형 등 큼직한 것들을 관리한다.
score도 마찬가지로 Static을 사용했기 때문에 0으로 꼭 초기화한다.
using UnityEngine; using TMPro; public class PlayUI : MonoBehaviour { public TextMeshProUGUI scoreText; void Update() { scoreText.text = GameManager.score.ToString(); } }
PlayUI 스크립트를 만들고 text 를 누적해서 받을 변수를 선언한다.
인스펙터 창에서 자기 자신을 드래그하여 넣어준다.
(텍스트를 필드 선언할 때 using TMPro; 를 꼭 추가해줘야 한다.)
그리고 GameManager에서 선언한 score를 string 형식으로 받는다.
void GetScore() { GameManager.score++; } void OnTriggerEnter2D(Collider2D coll) { if(coll.gameObject.tag == "Score") { GameManager.isDeath = false; GetScore(); } }
그리고 Player 스크립트로 돌아가서 Bird가 파이프를 통과했을 때
GameManager의 score가 1씩 누적 추가되도록 메서드 GetScore를 만들어서 작성하고
Trigger가 호출될 때 GetScore 메서드가 실행되도록 구현했다.
점수가 1씩 올라가는 것을 확인할 수 있다.
전체 코드
↓
더보기SpawnPoint.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SpawnPoint : MonoBehaviour { // 파이프 프리팹 public GameObject pipePrefab; // 스폰 시간 [SerializeField] float spawnTime = 1; // 타이머 private float countdown = 0; // 랜덤하게 나올 스폰 타임 [SerializeField] float spawnMaxTime = 1.1f; [SerializeField] float spawnMinTime = 0.9f; // 랜덤하게 나올 스폰 위치 [SerializeField] float spawnMaxY = 2.3f; [SerializeField] float spawnMinY = -1.3f; void Update() { // Death 상태이거나 Start 전이면 프리팹 생성을 멈춘다 if(GameManager.isStart == false || GameManager.isDeath == true) { return; } // 타이머 구현 countdown += Time.deltaTime; if (countdown >= spawnTime) { SpawnPipe(); countdown = 0; // 시간을 랜덤하게 스폰하기 spawnTime = Random.Range(spawnMinTime, spawnMaxTime); } } void SpawnPipe() { // 위치를 랜덤하게 스폰하기 float spawnY = transform.position.y + Random.Range(spawnMinY, spawnMaxY); Vector3 randomPosition = new Vector3(transform.position.x, spawnY, transform.position.z); // 파이프 프리팹 생성 Instantiate(pipePrefab, randomPosition, Quaternion.identity); } }
GameManager.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class GameManager : MonoBehaviour { // 플레이어 죽음 체크하기 public static bool isDeath = false; // 플레이어 시작 체크하기 public static bool isStart = false; // 스코어 public static int score = 0; void Start() { isDeath = false; isStart = false; score = 0; } }
PlayUI.cs
using UnityEngine; using TMPro; public class PlayUI : MonoBehaviour { public TextMeshProUGUI scoreText; void Update() { scoreText.text = GameManager.score.ToString(); } }
Player.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Player : MonoBehaviour { // Jump 구현 Rigidbody2D rb; [SerializeField] float Speed = 5f; private bool keyJump = false; // Rotate 구현 [SerializeField] private float upRotate = 5f; [SerializeField] private float downRotate = -5f; private Vector3 birdRotation; // Move 구현 [SerializeField] private float moveSpeed = 5f; // Ready 구현 [SerializeField] private float readyPower = 0.3f; void Start() { // RigidBody2D 컴포넌트를 rb라는 변수를 통해 가져온다 rb = this.GetComponent<Rigidbody2D>(); } void Update() { InputBird(); if(GameManager.isStart == false) { ReadyBird(); return; } RotateBird(); MoveBird(); } private void FixedUpdate() { // 게임 물리 연산은 FixedUpdate 메서드 안에서 진행한다 // 입력받은 Jump값이 true라면 if (keyJump == true) { // JumpBird메서드 받기 JumpBird(); // 그리고 다시 keyJump값은 false로 만들어준다 keyJump = false; } } void ReadyBird() { if (rb.velocity.y < 0) { rb.velocity = Vector2.up * readyPower; } } void JumpBird() { // Rigidbody의 velocity 는 Speed 만큼 올라간다 rb.velocity = Vector3.up * Speed; } void InputBird() { if(GameManager.isDeath == true) { return; } // 스페이스바 혹은 마우스 좌버튼을 눌렀을 때 keyJump |= Input.GetKeyDown(KeyCode.Space); keyJump |= Input.GetMouseButtonDown(0); // Bird가 시작했을 때 내려오지 않는 버그 수정 if(GameManager.isStart == false && keyJump == true) { GameManager.isStart = true; } } void RotateBird() { // upRotate와 downRotate를 누적해서 저장할 변수 degree 초기화 float degree = 0; if(rb.velocity.y > 0) { // upRotate 누적 degree = upRotate; } else if(rb.velocity.y < 0) { // downRotate 누적 degree = downRotate; } // birdRotation을 오일러각으로 변환하여 최댓값 30, 최솟값 -90을 받는다 birdRotation = new Vector3(0, 0, Mathf.Clamp((birdRotation.z + degree), -90, 30)); transform.eulerAngles = birdRotation; } void MoveBird() { if(GameManager.isDeath == true) { return; } // Bird가 앞으로 이동하는 것 구현하기 transform.Translate(Vector3.right * moveSpeed * Time.deltaTime, Space.World); } void GetScore() { GameManager.score++; } void OnTriggerEnter2D(Collider2D coll) { if(coll.gameObject.tag == "Score") { GameManager.isDeath = false; GetScore(); } } void OnCollisionEnter2D(Collision2D coll) { if(coll.gameObject.tag == "Pipe" || coll.gameObject.tag == "Ground") { GameManager.isDeath = true; } } }
'Unity 2D' 카테고리의 다른 글
[Unity 2D] Fly Bird 대기화면 UI 구현하기 (Animation조금 활용) (0) 2023.03.26 [Unity 2D] Fly Bird 게임오버 UI 구현하기 (Best Score 저장, Button 구현) (0) 2023.03.26 [Unity 2D] Fly Bird 충돌체와 충돌했을 때 Death 처리하기 (0) 2023.03.25 [Unity 2D] Fly Bird 파이프 프리팹 Spawn하기 (2) 2023.03.23 [Unity 2D] Fly Bird 프리팹 구현하고 Collider 적용하기 (0) 2023.03.23