Unity/정보

[Unity] 오브젝트 풀링 (Object pooling)

달시_Dalsi 2024. 1. 6. 02:37

 

오브젝트 풀링

여러가지 게임 중에 같은 오브젝트들이 반복해서 나오는 상황이 발생하는 게임이 있다.

예를 들어 아래 사진처럼 뱀서라이크 게임에서 같은 몬스터가 반복적으로 나올때라던지

 

오브젝트 풀링을 모른다면 위 상황을 연출할때 박쥐를 생성할땐 Instantiate를 사용하고 삭제할 때는 Destroy를 사용할 것이다. 하지만 Instantiate와 Destroy를 사용하면 안좋다는것은 조금만 구글링해도 금방 알 수 있듯이 이를 해결하기 위해 보통 오브젝트 풀링을 사용한다.

 

오브젝트 풀링이란 게임에서 자주 사용되는 객체를 미리 생성하여 필요할 때 활성화/비활성화를 통해 재활용하여 성능을 최적화하는 기법이다.

 

원리는 다음과 같다.

1. 풀링 생성: 게임이 시작될 때 미리 정해진 개수의 오브젝트를 생성하여 풀(오브젝트들을 관리할 공간)에 저장한다.

2. 오브젝트 재사용: 게임 실행 중에 오브젝트가 필요할 때마다 풀에서 사용 가능한 오브젝트를 꺼내서 재사용한다. 이때 생성과 소멸의 비용이 들지 않는다.

3. 재활용 및 관리: 오브젝트를 사용한 후에는 풀에 다시 넣어 재활용할 수 있도록 한다. 풀이 가득 차면 새로운 오브젝트를 동적으로 생성하여 풀에 추가할 수도 있다.

이러한 방식으로 오브젝트 풀링은 불필요한 객체 생성 및 소멸을 피하고, 게임의 성능을 최적화할 수 있다. 특히 모바일 기기나 리소스 제한이 있는 환경에서 유용하게 활용된다.

 

오브젝트 풀링을 직접 구현하는 방법도 있지만 여기선 유니티에서 지원하는 오브젝트 풀링을 사용할 것이다. 고로 네임스페이스에 using UnityEngine.Pool 를 추가하는 것을 잊지말자.

 

주요 스크립트

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


public class Spawner : MonoBehaviour
{
    [SerializeField] Transform Player;
    [SerializeField] GameObject prefabs_Monster;
    [SerializeField] int spawn_Count;
    [SerializeField] int spawn_radius;
    [SerializeField] int maxPoolsize;

    private IObjectPool<Monster> _Pool;

    void Start()
    {
        _Pool = new ObjectPool<Monster>(CreateMonster, OnGetMonster, OnReleaseMonster, OnDestroyMonster, true, 10, maxPoolsize);
        StartCoroutine(spawn());
    }

    IEnumerator spawn()
    {
        WaitForSeconds waitflag = new WaitForSeconds(0.1f);

        for (int i = 0; i < spawn_Count; i++)
        {
            var monster = _Pool.Get();
            Vector2 pos_randOnSpherePos = Random.onUnitSphere * spawn_radius;
            monster.transform.position = new Vector3(pos_randOnSpherePos.x, 0, pos_randOnSpherePos.y);
            monster.transform.LookAt(Player.position);
            yield return waitflag;
        }
    }

    private Monster CreateMonster()
    {
        Monster monster = Instantiate(prefabs_Monster).GetComponent<Monster>();
        monster.SetManagedPool(_Pool);
        return monster;
    }

    private void OnGetMonster(Monster monster)
    {
        monster.gameObject.SetActive(true);
    }

    private void OnReleaseMonster(Monster monster)
    {
        monster.gameObject.SetActive(false);
    }
    private void OnDestroyMonster(Monster monster)
    {
        Destroy(monster.gameObject);
    }
}

 

 

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

public class Monster : MonoBehaviour
{
    private IObjectPool<Monster> Monsterpool;

    void Update()
    {
       transform.Translate(Vector3.forward * 5 * Time.deltaTime);
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            DestroyMonster();
        }
    }

    public void SetManagedPool(IObjectPool<Monster> pool)
    {
        this.Monsterpool = pool;
    }

    public void DestroyMonster()
    {
        this.Monsterpool.Release(this);
    }
}

 

결과

 

'Unity > 정보' 카테고리의 다른 글

[Unity] 2D 랜덤 맵 생성(Celluar Automata)  (0) 2024.01.20
[Unity] New Input System  (1) 2024.01.13
[Unity] 모바일 게임 성능 최적화  (0) 2024.01.02
[Unity] 사운드 매니저  (0) 2023.12.03
[Unity] AOS Fog of War 에셋  (0) 2023.12.02