말감로그

[Unity] 디자인 패턴 - 오브젝트 풀링 본문

Unity

[Unity] 디자인 패턴 - 오브젝트 풀링

habbn 2025. 2. 20. 00:44
728x90

오브젝트 풀링

빈번하게 사용하는 객체 및 오브젝트에 대하여 매번 새로 생성하고 삭제하는 것이 아닌 미리 생성한 오브젝트를 재사용하는 기법이다.

 

유니티에서 오브젝트를 생성하거나 삭제할 때 Instantiate()와 Destroy() 함수를 사용하는데, 새로 할당하고 삭제하는 과정에서 많은 시간과 메모리를 잡아먹는다. (가비지 컬렉터가 자주 발생 , 메모리 단편화 발생)

 

예제 코드 

(1) Bullet 스크립트

using UnityEngine;

public class Bullet : MonoBehaviour
{
    private float speed = 10f;

    public void Init(Vector3 direction)
    {
        GetComponent<Rigidbody>().velocity = direction * speed;
        Invoke(nameof(ReturnToPool), 2f); // 2초 후 자동 반환
    }

    private void ReturnToPool()
    {
        gameObject.SetActive(false);
    }
}

 

(2) ObjectPool 스크립트

using System.Collections.Generic;
using UnityEngine;

public class ObjectPool : MonoBehaviour
{
    public GameObject prefab; // 미리 생성할 프리팹
    public int poolSize = 10; // 초기 생성 개수

    private Queue<GameObject> pool = new Queue<GameObject>();

    private void Start()
    {
        for (int i = 0; i < poolSize; i++)
        {
            GameObject obj = Instantiate(prefab);
            obj.SetActive(false);
            pool.Enqueue(obj);
        }
    }

    public GameObject GetObject()
    {
        if (pool.Count > 0)
        {
            GameObject obj = pool.Dequeue();
            obj.SetActive(true);
            return obj;
        }
        else
        {
            GameObject newObj = Instantiate(prefab);
            return newObj;
        }
    }

    public void ReturnObject(GameObject obj)
    {
        obj.SetActive(false);
        pool.Enqueue(obj);
    }
}

 

(3) 총알을 발사하는 GunController 스크립트

using UnityEngine;

public class GunController : MonoBehaviour
{
    public ObjectPool bulletPool;
    public Transform firePoint;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space)) // 스페이스바를 누르면 총알 발사
        {
            Shoot();
        }
    }

    void Shoot()
    {
        GameObject bullet = bulletPool.GetObject();
        bullet.transform.position = firePoint.position;
        bullet.transform.rotation = firePoint.rotation;
        bullet.GetComponent<Bullet>().Init(firePoint.forward);
    }
}

 

 

최적화 팁

1. 오브젝트가 너무 많이 생성되지 않도록 풀 크기를 적절히 조절

2. ReturnToPool()을 호출할 때 CancelInvoke()를 사용하여 중복 실행 방지

3. OnDisable()을 활용하면 풀로 반환되는 시점을 자동으로 처리 가능

 

728x90