본문 바로가기
Hello, World!/Unity

유니티 2D 런게임을 만들자(7)

by 27일 낮 2022. 3. 14.
728x90

지난번에 풀링을 했다!

 

필요한 부분을 만들어놨다가 꺼내와서 사용

 

 

닷지 할 땐 매번 필요할 때마다 생성하고 파괴했었음 -> 많은 문제 발생

 

그래서 미리 사용할 오브젝트들을 게임 시작 전 생성해놓고

특정한 공간(pool)! 웅덩이!!!

 


PlatformSpawner.cs

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

// 이전 총알생성기에서 사용했던 방식인
// 매번 필요시마다 사용했던 Instantiate(생성) 이 아닌
// 오브젝트 풀링 방식을 사용할 거임
// 오브젝트 풀링(Object Pooling)?
// '풀(Pool):웅덩이'에 쌓아두는 방식임
// 왜 해당 방식이 필요하냐
// Instantiate() 메서드처럼 오브젝트를 실시간으로 생성하거나,
// Destroy() 메서드처럼 오브젝트를 실시간으로 파괴하는 처리는
// 성능을 많이 요구함
// 또한 메모리를 정리하는 GC(GarbageCollection)을 유발하기 쉬움
// 게임 도중에 오브젝트를 너무 자주 생성하거나 파괴하면
// 게임 끊김(Freeze) 현상이 발생 됨

// 발판을 생성하고 주기적으로 재배치하는 스크립트
public class PlatformSpawner : MonoBehaviour
{
    // 생성할 발판의 원본 프리팹
    public GameObject platformPrefab;
    // 생성할 발판 수
    public int count = 3;

    // 다음 배치까지의 시간 간격 최솟값
    public float timeBetSpawnMin = 1.25f;
    // 다음 배치까지의 시간 간격 최댓값
    public float timeBetSpawnMax = 2.25f;
    // 다음 배치까지의 시간 간격
    private float timeBetSpawn;

    // 배치할 위치의 최소 y값
    public float yMin = -3.5f;
    // 배치할 위치의 최대 y값
    public float yMax = 1.5f;
    // 배치할 위치의 x값
    private float xPos = 20f;

    // 미리 생성한 발판들을 보관할 배열
    private GameObject[] platforms;
    // 사용할 현재 순번의 발판
    private int currentIndex = 0;

    // 초반에 생성한 발판을 화면 밖에 숨겨둘 위치
    private Vector2 poolPosition = new Vector2(0, -25);
    // 마지막 배치 시점
    private float lastSpawnTime;

    void Start()
    {
        // 변수를 초기화하고 사용할 발판을 미리 생성

        // count만큼의 공간을 가지는 새로운 발판 배열 생성
        platforms = new GameObject[count];

        // count만큼 루프하면서 발판 생성
        for (int i = 0; i < count; i++)
        {
            // platformPrefab을 원본으로 새 발판을
            // poolPosition 위치에 복제 생성
            // 생성된 발판을 platforms 배열에 할당
            platforms[i] = Instantiate(platformPrefab, poolPosition, Quaternion.identity);
            // Quaternion.Euler(new Vector3(0, 0, 0));
        }

        // 마지막 배치 시점 초기화
        lastSpawnTime = 0f;
        // 다음번 배치까지의 시간 간격을 초기화
        timeBetSpawn = 0f;
    }

    void Update()
    {
        // 순서를 돌아가며 주기적 발판을 배치

        // 게임오버 상태에서는 동작하지 않음
        if (GameManager.instance.isGameover) return;

        // 마지막 배치 시점에서 timeBetSpawn 이상 시간이 흘렀다면,
        if (Time.time >= lastSpawnTime + timeBetSpawn)
        {
            // 기록된 마지막 배치 시점을 현재 시점으로 갱신
            lastSpawnTime = Time.time;

            // 다음 배치까지의 시간 간격을 timeBetSpawnMin, timeBetSpawnMax 사이에서 랜덤 가져오기
            timeBetSpawn = Random.Range(timeBetSpawnMin, timeBetSpawnMax);

            // 배치할 위치의 높이를 yMin과 yMax 사이에서 랜덤 가져오기
            float yPos = Random.Range(yMin, yMax);

            // 사용할 현재 순번의 발판 게임 오브젝트를 비활성화하고
            // 바로 즉시 다시 활성화. 이 때, 발판의 Platform 컴포넌트의 OnEnable() 메서드가 실행됨
            platforms[currentIndex].SetActive(false);
            platforms[currentIndex].SetActive(true);

            // 현재 순번의 발판을 화면 오른쪽에 재배치
            platforms[currentIndex].transform.position = new Vector2(xPos, yPos);

            // 순번 넘기기
            currentIndex++;

            // 마지막 순번에 도달했다면...
            if (currentIndex >= count)
            {
                currentIndex = 0;
            }
        }
    }
}
  • 발판을 만들 땐, x값을 고정하고 y 값을 랜덤으로 줄거임

 

  • Instantiate(platformPrefab, poolPosition, Quaternion.identity);
    • Istantiate(생성할 거, 위치, 회전값)
    • Quaternion.identity
      얘랑 같은 말임! Quaternion.Euler(new Vector3(0, 0, 0));

 

  • Time.time
    • 한 프레임에서 흐른 시간을 확인하기 위해 쓴다
    • 게임이 시작되고 얼마만큼의 시간이 흘렀는지 확인해주는 메서드!

 


빈 오브젝트 PlatformSpawner 생성

스크립트 할당하고, Platform 프리팹을 넣어준다

 

 

 

플레이 했을 때 장애물을 밟아도 죽지 않는다??

=> 우리는 충돌이 생겼을 때 태그를 확인하기로 했음! 근데 얘는 태그 지정이 안돼있었다.

Dead로 태그를 변경해주자

 

태그 확인!!

또한 isTrigger 체크하기!!!!!!

 

 

발판을 밟았을 때 score++,

장애물을 밟았을 때 멈추고 게임오버가 뜨면 성공!

 

 

 

 

이제 배경음악을 깔아주자

그냥 music을 Hierarchy뷰에 넣어주면 됨

Play On Awake, Loop 체크!

 

 

 


빌드 준비하자

Android 앱으로 만들어줄거임

Platform을 Android 선택 후 Switch Platform을 눌러주면 안드로이드에 맞게 바뀜!

(사진은 이미 바껴있음)

근데 원래 Platform 세팅하고 개발을 시작한다..! 우리는 늦게 해준 것,,,,

플랫폼 변경 작업이 하루 이상 소요될 수도 있다!

댓글