상세 컨텐츠

본문 제목

13장 유니런(발판 반복 생성, 오브젝트 풀링)

유니티/게임만들기

by MJ_119 2024. 3. 26. 02:08

본문

- 발판구현

- OnEnable() 메서드

- 발판 생성기 구현

- 오브젝트 풀링

- 미리 생성된 발판을 재사용하는 방법

 

@ 발판 만들기 

 - 시작지점 이후의 발판을 캐릭터가 밟을 경우 점수가 올라가는 기능 구현

 - 발판 위에 장애물 생성하는 기능 구현

 

 

프리팹으로 생성한 오브젝트의 레이어를 설정해준다.

장애물 오브젝트는 배경보다는 앞에, 캐릭터와 발판보다는 뒤에 Middle 레이어로 변경

 

@ OnEnable() 메서드

 : 컴포넌트가 활성화될 때마다 매번 다시 실행.

 컴포넌트를 끄고 다시 켜는 방식으로 재실행 할 수 있음.

 - 개별 컴포넌트를 끄고 켜지 않고, 게임오브젝트를 끄고 켜는 방식으로도 재실행 가능.

 활용 : 게임 오브젝트가 활성화될 때마다 상태를 리셋하는 기능을 구현할 때 주로 이용. OnEnable()에 초기화 코드를 넣어두고, 게임 오브젝트의 정보를 리셋해야 할 때마다 게임 오브젝트를 끄고 다시 켜는 방식으로 활용.

 

// 컴포넌트가 활성화될때 마다 매번 실행되는 메서드
    private void OnEnable() {
        // 발판을 리셋하는 처리

        // 밟힘 상태를 리셋
        stepped = false;

        // 장애물 수 만큼 루프
        for ( int i = 0; i < obstacles.Length; i++ )
        {
            // 현재 순번의 장애물을 1/3의 확률로 활성화
            if( Random.Range(0,3) == 0 )
            {
                obstacles[i].SetActive(true);
            }
            else
            {
                obstacles[i].SetActive(false);
            }
        }
    }

 

밟힘상태를 false로 초기화한후, 순번 i를 0부터 시작해 장애물 수 obstacles.Length에 도달하기 전까지 1씩 증가시킴.

 그뒤 1/3 확률로 장애물 오브젝트 활성화.

- Random.Range(0,3)은 0,1,2 중에서 한 숫자를 랜덤으로 반환.

 

 

@ 발판 밟으면 점수 추가

    void OnCollisionEnter2D(Collision2D collision) {
        // 플레이어 캐릭터가 자신을 밟았을때 점수를 추가하는 처리

        // 충돌한 태그가 Player이고, 캐릭터가 이전에 밟지 않았다면
        if (collision.collider.tag == "Player" && stepped == false )
        {
            // 점수를 추가하고 밟힘 상태를 true로 변경
            stepped = true;
            GameManager.instance.AddScore(1); // 1점 추가
        }
    }

 

같은 발판을 여러번 밟아서 점수 올라가는 것을 방지하기 위해 아직 안밟힌 발판인지 조건문에 추가 한 후 점수 추가

 

 

오브젝트 변경 한게 있으면 프리팹 선택후 Overrides > Apply All 클릭해서 프리팹에 반영 시킴.

 

@ 발판 생성기 만들기 ( 오브젝트 풀링 )

오브젝트 풀링 : 초기에 필요한 만큼 오브젝트를 미리 만들어 풀에 쌓아두는(저장해 놓는) 방식.

 - 오브젝트가 필요할 때에는 오브젝트를 풀에서 가져다 씀.

 - 오브젝트가 필요 없을 때에는 오브젝트를 파괴하지 않고 비활성화하고 풀에 반환.

 

Instantiate() 메서드 처럼 오브젝트를 실시간으로 생성하거나, Destroy() 메서드처럼 오브젝트를 실시간으로 파괴하는 처리는 성능을 많이 요구함.

 또 메모리를 정리하는 GC( 가비지 컬렉션 )를 유발하기 쉬움. => 생성 및 삭제가 많아질수록 끊김 현상 발생

 

오브젝트 풀링은 게임 초반에 미리 생성함 => 로딩 시간이 길어짐. => 대신 게임 끊김 현상은 거의 없음.

 

@ PlatformSpawner 스크립트 작성하기

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() {
        // 변수들을 초기화하고 사용할 발판들을 미리 생성
        // count만큼의 공간을 가지는 새로운 발판 배열 생성
        platforms = new GameObject[count];

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

        // 마지막 배치 시점 초기화
        lastSpawnTime = 0f;
        // 다음번 배치까지의 시간 간격을 0으로 초기화
        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;
            }
        }
    }
}

 

Time.time은 유니티 라이브러리에 내장되어 있으며, 게임 시작 후 시간이 몇 초 지났는지 출력하는 변수.

 - 따라서 현재시점으로 취급할 수 있음.

 

lastSpawnTime + timeBetSpawn은 다음번 배치가 예약된 시점.

 

 

 

 

 

 

 

 

@ 배경음악 넣기

 

 

배경음악 파일을 넣고 - 루프 체크.

 

@ 빌드하기

 

 

Add Open Scenes 눌러준 후 Build And Run으로 폴더 선택 후 빌드!

관련글 더보기