
어떤 상황에서 어떤 Anim를 실행할지
한번에 하나의 상태가 되도록 해야됨

Awake는 Start보다 1 프레임 더 빠르게 진행됨.
기존의 text보다 더 활용도 높은 ui
기존의 폰트를 사용하고 싶다면?

- Font Asset Creator하고 선택 후 Generate


using UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;
// 게임 오버 상태를 표현하고, 게임 점수와 UI를 관리하는 게임 매니저
// 씬에는 단 하나의 게임 매니저만 존재할 수 있다.
public class GameManager : MonoBehaviour {
public static GameManager instance; // 싱글톤을 할당할 전역 변수
public bool isGameover = false; // 게임 오버 상태
public TextMeshProUGUI scoreText; // 점수를 출력할 UI 텍스트
public GameObject gameoverUI; // 게임 오버시 활성화 할 UI 게임 오브젝트
private int score = 0; // 게임 점수
// 게임 시작과 동시에 싱글톤을 구성
void Awake() {
// 싱글톤 변수 instance가 비어있는가?
if (instance == null)
{
// instance가 비어있다면(null) 그곳에 자기 자신을 할당
instance = this;
}
else
{
// instance에 이미 다른 GameManager 오브젝트가 할당되어 있는 경우
// 씬에 두개 이상의 GameManager 오브젝트가 존재한다는 의미.
// 싱글톤 오브젝트는 하나만 존재해야 하므로 자신의 게임 오브젝트를 파괴
Debug.LogWarning("씬에 두개 이상의 게임 매니저가 존재합니다!");
Destroy(gameObject);
}
}
void Update() {
// 게임 오버 상태에서 게임을 재시작할 수 있게 하는 처리
if (isGameover && Input.GetMouseButtonDown(0))
{
// 현재 씬 가져옴
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
// 점수를 증가시키는 메서드
public void AddScore(int newScore) {
if (!isGameover)
{
score += newScore;
scoreText.text = "Score: " + score;
}
}
// 플레이어 캐릭터가 사망시 게임 오버를 실행하는 메서드
public void OnPlayerDead()
{
isGameover = true;
gameoverUI.SetActive(true);
}
}매번 Instantiate와 destroy를 하면 많은 계산이 발생.
너무 자주 생성하거나 파괴하면 끊긴다.
→ 필요할 때 Pool에서 가져오고, 아니면 반납한다.
using UnityEngine;
// 발판을 생성하고 주기적으로 재배치하는 스크립트
public class PlatformSpawner : MonoBehaviour {
public GameObject platformPrefab; // 생성할 발판의 원본 프리팹
public int count = 3; // 생성할 발판의 개수
public float timeBetSpawnMin = 1.25f; // 다음 배치까지의 시간 간격 최솟값
public float timeBetSpawnMax = 2.25f; // 다음 배치까지의 시간 간격 최댓값
private float timeBetSpawn; // 다음 배치까지의 시간 간격
public float yMin = -3.5f; // 배치할 위치의 최소 y값
public float yMax = 1.5f; // 배치할 위치의 최대 y값
private float xPos = 20f; // 배치할 위치의 x 값
private GameObject[] platforms; // 미리 생성한 발판들
private int currentIndex = 0; // 사용할 현재 순번의 발판
private Vector2 poolPosition = new Vector2(0, -25); // 초반에 생성된 발판들을 화면 밖에 숨겨둘 위치
private float lastSpawnTime; // 마지막 배치 시점
void Start() {
// 변수들을 초기화하고 사용할 발판들을 미리 생성
platforms = new GameObject[count];
for (int i = 0; i < count; i++)
{
platforms[i] = Instantiate(platformPrefab, poolPosition, Quaternion.identity);
}
lastSpawnTime = 0f;
timeBetSpawn = 0;
}
void Update() {
// 순서를 돌아가며 주기적으로 발판을 배치
if (GameManager.instance.isGameover) return;
if (Time.time >= lastSpawnTime + timeBetSpawn)
{
lastSpawnTime = Time.time;
timeBetSpawn = Random.Range(timeBetSpawnMin, timeBetSpawnMax);
float yPos = Random.Range(yMin, yMax);
platforms[currentIndex].SetActive(false);
platforms[currentIndex].SetActive(true);
platforms[currentIndex].transform.position = new Vector2(xPos, yPos);
currentIndex++;
if (currentIndex >= count)
{
currentIndex = 0;
}
}
}
}