[Unity][2D-Game] Suika-Game (7)

suhan0304·2023년 11월 19일
0

유니티 - Suika Game

목록 보기
7/8
post-thumbnail

Review

  • 오디오 소스를 추가해서 사운드 시스템을 구현하였다.
  • BGM의 경우 BGM Player로 재생한다.
  • SFX의 경우 세 개의 SFX Player로 재생하도록 구현하였다.

강의영상 (7) - 오브젝트 풀링


개발

오브젝트 풀링

Instantiate, Destroy를 사용할수록 파편화된 메모리가 누적된다. 따라서 Instantiate, Destroy를 최소한으로 사용하기 위해 오브젝트를 새로 복제, 파괴하기 전에 오브젝트를 오브젝트 풀 안에서 유지관리하면서 사전에 사용했던 오브젝트를 풀로부터 다시 가져와서 활용하는 방식을 오브젝트 풀링이라고 한다.


풀 생성

게임 매니저에 Dongle과 ParticleSystem 오브젝트가 저장될 리스트들을 선언해서 풀을 만들어준다.

오브젝트풀 관리를 위한 사이즈, 커서 변수또한 추가해준다.

GameManager.cs

public GameObject donglePrefab; //동글 프리팹
public Transform dongleGroup;   //동글이 생성될 위치
public List<Dongle> donglePool;

public GameObject effectPrefab; //이펙트 프리팹
public Transform effectGroup;   //이펙트가 생성될 위치
public List<ParticleSystem> effectPool;

[Range(1, 30)]
public int poolSize;
public int poolCursor;

[Range(N, M)] : 인스펙터 창에서 슬라이더 형식으로 N부터 M까지의 값을 조절할 수 있다.

오브젝트 풀을 만들기 위한 함수를 생성한다.

private void Awake()
{
    Application.targetFrameRate = 60;

    donglePool = new List<Dongle>();
    effectPool = new List<ParticleSystem>();

    for (int i = 0; i < poolSize; i++)
    {
        MakeDongle(); //풀 만들기
    }
}

Dongle MakeDongle()
{
    //이펙트 생성
    GameObject instantEffectObj = Instantiate(effectPrefab, effectGroup);
    instantEffectObj.name = "Effect " + effectPool.Count; //이름을 설정
    ParticleSystem instantEffect = instantEffectObj.GetComponent<ParticleSystem>();
    effectPool.Add(instantEffect);

    //동글 프리팹 복사해서 가져옴, 이 때 부모는 동글 그룹으로 설정
    GameObject instantDongleObj = Instantiate(donglePrefab, dongleGroup);
    instantDongleObj.name = "Dongle " + donglePool.Count; //이름을 설정
    Dongle instantDongle = instantDongleObj.GetComponent<Dongle>();
    instantDongle.manager = this; //manager 변수도 초기화
    instantDongle.effect = instantEffect;
    donglePool.Add(instantDongle);

    return instantDongle;
}

poolSize를 10으로 설정하고 Run하면 아래 사진과 같이 Dongle, Effect가 각각 10개씩 만들어진 것을 확인할 수 있다.


풀 사용

이제 생성된 동글을 사용하도록 GetDongle을 수정한다.

GameManager.cs

Dongle GetDongle()
{
    for(int i=0;i<donglePool.Count;i++)
    {
        poolCursor = (poolCursor+1) % donglePool.Count; //커서가 오브젝트 풀을 계속 회전하도록 설정
        if(!donglePool[poolCursor].gameObject.activeSelf) //비활성화된 오브젝트를 찾으면 해당 오브젝트를 사용
        {
            return donglePool[poolCursor]; //비활성화 되어있는 동글을 넘김
        }
    }
    return MakeDongle(); //만약 donglePool에 없다면 MakeDongle로 풀에 하나 추가해서 넘김
}

이 때 Run을 해보면 재사용되는 동글이 기존에 비활성화됐던 위치 그대로 나타나는 것을 확인할 수 있다. 이를 재사용 로직을 구현해서 보완한다.


재사용 로직

동글이 합쳐지면서 비활성화 될 때 모든 정보를 초기화해주기 위해 OnDisable 함수를 이용해 로직을 구현한다.

Dongle.cs

void OnDisable()
{
    //동글 속성 초기화
    level = 0;
    isDrag = false;
    isMerge = false;
    isAttach = false;

    //동글 트랜스폼 초기화
    transform.localPosition = Vector3.zero;
    transform.localRotation = Quaternion.identity;
    transform.localScale = Vector3.zero;

    //동글 물리 초기화
    rigid.simulated = false;
    rigid.velocity = Vector2.zero;
    rigid.angularVelocity = 0;
    circle.enabled = true;
}

결과물

하이어라키 창의 오브젝트들의 활성화/비활성화를 보면 오브젝트 풀링이 정상 작동하고 있다는 것을 알 수 있다.

profile
Be Honest, Be Harder, Be Stronger

0개의 댓글