🗨 개인적인 공부 기록용으로 정리한 내용입니다. 잘못된 내용에 대한 피드백은 언제나 감사합니다 :)
⭐ 오브젝트 풀은 반복적으로 생성/소멸되는 객체(`오브젝트`)를 풀(`Pool`)에 미리 생성 및 저장해 두고 필요시 꺼내 쓰고, 사용이 끝나면 다시 반환하여 관리하는 디자인 패턴이다.
게임 개발을 하다 보면 특정 객체(`Object`)는 생성하고 소멸시키는 작업을 자주 해야 하는 상황이 생긴다.
특히 총알, 적(Enemy), 파티클 이펙트처럼 짧은 시간에 생성과 소멸이 반복되는 오브젝트들은 성능 저하의 주요 원인이 된다.
이때, 생성/소멸의 부담을 크게 줄여 성능을 최적화시키는 패턴이 바로 오브젝트 풀(Object Pool) 패턴이다.
📌 오브젝트 풀이란?
- 오브젝트를 미리 생성하여 풀(`Pool`)에 저장해 두고, 필요하면 풀에서 꺼내 쓰고, 사용이 끝나면 다시 풀로 돌려보낸다.
- 많은 수의 오브젝트를 생성하고 파괴할 때 CPU의 부담을 줄이는 최적화 기법이다.
- 로딩 시간에 오브젝트를 미리 만들어 풀에 담아두고, 런타임에는 사용하기만 하는 식으로 구현한다.

📌 오브젝트 풀을 왜 사용하는가?
오브젝트 풀은 주로 성능과 메모리 관리 최적화를 위해 사용한다.
특히 Unity에서 오브젝트 풀을 FPS, 슈팅 게임, 그리고 다양한 장르에서 성능을 최적화하는 필수적인 도구로 쓰인다.
- 성능 최적화
- 객체를 자주 생성하고 파괴하는 작업은 메모리 할당 및 해제에 따른 오버헤드가 크다. 이는 성능 저하의 주요 원인이다.
- 오브젝트 풀을 사용하면 객체를 재사용함으로써 성능을 개선할 수 있다.
- 가비지 컬렉션(GC) 부담 감소
- 빈번한 메모리 할당 및 해제는 가비지 컬렉션을 유발하여 프레임 드랍이 발생할 수 있다.
- 오브젝트 풀로 가비지 컬렉션 급증으로 인해 발생할 수 있는 밑줄 끊김 현상(Hiccup, GC spike)을 예방할 수 있다.
- 일정한 메모리 사용
- 한 번에 생성할 수 있는 오브젝트의 개수를 제한할 수 있다.
- (반대로, 생성하고 사용하지 않을 경우 메모리 낭비가 되는 단점이 있다.)
📌 오브젝트 풀의 구조와 구현
오브젝트 풀의 기본 구성 요소는 Pool, Pool Manager(관리자), Client(사용자)로 나눌 수 있다.
- Pool
- 미리 생성된 객체를 저장
- 일반적으로 `List`, `Queue`, 혹은 `Stack` 자료 구조를 사용한다. (아래 예시코드는 `Stack` 사용)
- Pool Manager(관리자)
- Pool에서 객체를 가져오거나 반환하는 역할 담당
- 필요한 경우 새로운 객체를 생성하거나 Pool에 반환
- Client(사용자)
- 오브젝트 풀에 객체를 요청해서 사용 후 반환
🔖 Object Pool
Unity에서 사용하는 기본적인 오브젝트 풀(Object Pool)의 구현 예시이다.
예시 코드 | 오브젝트 풀(Object Pool)
🌞 유니티에서 배포한 코드입니다.
/* 오브젝트 풀 */
public class ObjectPool : MonoBehaviour
{
[SerializeField] private uint initPoolSize; // 풀(Pool) Size 설정
[SerializeField] private PooledObject objectToPool;
private Stack<PooledObject> stack; // 풀링된 오브젝트들을 담는 스택
private void Start()
{
SetupPool(); // 게임 플레이 중 한 번 실행
}
/* 풀 생성 */
private void SetupPool()
{
stack = new Stack<PooledObject>();
PooledObject instance = null;
for (int i = 0; i < initPoolSize; i++) // 위에서 정한 initPoolSize만큼 생성
{
instance = Instantiate(objectToPool);
instance.Pool = this;
instance.gameObject.SetActive(false); // 비활성화 🔴 (준비 단계이기 때문에 비활성 해놓기)
stack.Push(instance);
}
}
/* 풀에서 첫 번째 액티브 게임 오브젝트를 반환 */
public PooledObject GetPooledObject()
{
/* 풀이 비어있으면(=더이상 꺼낼 오브젝트가 없으면), 새로운 PooledObjects를 인스턴스화*/
if (stack.Count == 0)
{
PooledObject newInstance = Instantiate(objectToPool);
newInstance.Pool = this;
return newInstance; // 일회성 인스턴스
}
/* 그렇지 않으면, 풀에서 다음 요소(인스턴스)를 꺼냄 */
PooledObject nextInstance = stack.Pop();
nextInstance.gameObject.SetActive(true); // 활성화 🔵
return nextInstance;
}
/* 사용이 끝난 오브젝트를 풀에 반환할 때 호출 */
public void ReturnToPool(PooledObject pooledObject)
{
stack.Push(pooledObject);
pooledObject.gameObject.SetActive(false); // 비활성화 🔴
}
}
풀링된 오브젝트(Client)는 ObjectPool.cs을 참조하기 위해 아래 PooledObject 컴포넌트를 가진다.
/* Object Pool의 관리 대상인 오브젝트 */
public class PooledObject : MonoBehaviour
{
private ObjectPool pool;
public ObjectPool Pool { get => pool; set => pool = value; }
/* 게임 오브젝트가 비활성화되고 풀로 반환하는 함수 */
public void Release()
{
pool.ReturnToPool(this);
}
}
🔖 UnityEngine.Pool (유니티 API)
유니티 2021 버전부터 자체적으로 오브젝트 풀(스택 기반) API을 제공한다. 🔗 Unity Doc
UnityEngine.Pool 은 유니티에서 제공하는 기본 Object Pooling 라이브러리다.
`using UnityEngine.Pool`로 사용이 가능하며, 기본적인 인터페이스가 구현되어 있다.
오브젝트 풀을 처음부터 만들 필요가 없어 시간을 단축할 수 있다.
🧩 제공하는 기능
- 오브젝트 생성하여, `Pool`을 채운다.
- `Pool`에서 가져오기
- `Pool`로 반환하기
- 풀링 된 오브젝트 파괴하기
- 주로 최대한도에 도달한 경우 사용한다.
예시 코드 | UnityEngine.Pool API 사용
using UnityEngine.Pool;
public class RevisedGun : MonoBehaviour
{
…
// Unity 2021 이상 버전에서 사용 가능한 스택 기반 ObjectPool
private IObjectPool<RevisedProjectile> objectPool;
// 이미 풀에 있는 기존 항목을 반환하려 할 때 예외를 반환
[SerializeField] private bool collectionCheck = true;
// 풀의 용량과 최대 크기를 제어하는 추가 옵션
[SerializeField] private int defaultCapacity = 20;
[SerializeField] private int maxSize = 100;
private void Awake()
{
objectPool = new ObjectPool<RevisedProjectile>(CreateProjecti
le,
OnGetFromPool, OnReleaseToPool, OnDestroyPooledObject,
collectionCheck, defaultCapacity, maxSize);
}
// 오브젝트 풀을 채울 항목을 만들 때 호출됨
private RevisedProjectile CreateProjectile()
{
RevisedProjectile projectileInstance =
Instantiate(projectilePrefab);
projectileInstance.ObjectPool = objectPool;
return projectileInstance;
}
// 오브젝트 풀로 항목을 반환할 때 호출됨
private void OnReleaseToPool(RevisedProjectile pooledObject)
{
pooledObject.gameObject.SetActive(false);
}
// 오브젝트 풀에서 다음 항목을 검색할 때 호출됨
private void OnGetFromPool(RevisedProjectile pooledObject)
{
pooledObject.gameObject.SetActive(true);
}
// 풀링된 항목의 최대 개수를 초과할 때 호출됨(풀링된 오브젝트 파괴)
private void OnDestroyPooledObject(RevisedProjectile pooledObject)
{
Destroy(pooledObject.gameObject);
}
private void FixedUpdate()
{
…
}
}
📌 오브젝트 풀의 단점
오브젝트 풀의 문제점으로는 메모리 낭비 가능성이 있다.
- 필요 이상의 객체를 미리 생성하면 메모리가 낭비될 수 있다.
- 사용되지 않는 객체도 메모리를 점유한다.
Thread-Safe 하지 않다.
- 멀티스레드에서 사용하기 위해선 동기작업이 필요하다.
참고
게임 프로그래밍 패턴으로 코딩 스킬 업그레이드
새로운 전자책에서는 잘 알려진 디자인 패턴과 함께 실제 Unity 프로젝트에서 활용할 수 있는 실용적인 예제를 소개합니다.
unity.com
Object pool pattern - Wikipedia
Object pool pattern - Wikipedia
From Wikipedia, the free encyclopedia Software creational design pattern The object pool pattern is a software creational design pattern that uses a set of initialized objects kept ready to use – a "pool" – rather than allocating and destroying them on
en.wikipedia.org
오브젝트 풀링을 사용하여 Unity에서 C# 스크립트 성능 향상하기
오브젝트 풀링을 사용하여 Unity에서 C# 스크립트 성능 향상하기
이 페이지에서는 오브젝트 풀링과 이를 통해 게임 성능을 개선하는 방법에 대해 설명합니다. 여기에는 프로젝트에 Unity의 빌트인 오브젝트 풀링 시스템을 구현하는 방법에 대한 예제가 포함되
unity.com
'👻 Unity' 카테고리의 다른 글
[Unity] 싱글톤 패턴(Singleton Pattern): 오직 하나뿐인 객체 (0) | 2024.11.27 |
---|---|
[Unity] 유니티 설치 실패: Validation Failed 원인 및 해결 방법 (0) | 2024.08.20 |
🗨 개인적인 공부 기록용으로 정리한 내용입니다. 잘못된 내용에 대한 피드백은 언제나 감사합니다 :)
⭐ 오브젝트 풀은 반복적으로 생성/소멸되는 객체(오브젝트
)를 풀(Pool
)에 미리 생성 및 저장해 두고 필요시 꺼내 쓰고, 사용이 끝나면 다시 반환하여 관리하는 디자인 패턴이다.
게임 개발을 하다 보면 특정 객체(Object
)는 생성하고 소멸시키는 작업을 자주 해야 하는 상황이 생긴다.
특히 총알, 적(Enemy), 파티클 이펙트처럼 짧은 시간에 생성과 소멸이 반복되는 오브젝트들은 성능 저하의 주요 원인이 된다.
이때, 생성/소멸의 부담을 크게 줄여 성능을 최적화시키는 패턴이 바로 오브젝트 풀(Object Pool) 패턴이다.
📌 오브젝트 풀이란?
- 오브젝트를 미리 생성하여 풀(
Pool
)에 저장해 두고, 필요하면 풀에서 꺼내 쓰고, 사용이 끝나면 다시 풀로 돌려보낸다. - 많은 수의 오브젝트를 생성하고 파괴할 때 CPU의 부담을 줄이는 최적화 기법이다.
- 로딩 시간에 오브젝트를 미리 만들어 풀에 담아두고, 런타임에는 사용하기만 하는 식으로 구현한다.

📌 오브젝트 풀을 왜 사용하는가?
오브젝트 풀은 주로 성능과 메모리 관리 최적화를 위해 사용한다.
특히 Unity에서 오브젝트 풀을 FPS, 슈팅 게임, 그리고 다양한 장르에서 성능을 최적화하는 필수적인 도구로 쓰인다.
- 성능 최적화
- 객체를 자주 생성하고 파괴하는 작업은 메모리 할당 및 해제에 따른 오버헤드가 크다. 이는 성능 저하의 주요 원인이다.
- 오브젝트 풀을 사용하면 객체를 재사용함으로써 성능을 개선할 수 있다.
- 가비지 컬렉션(GC) 부담 감소
- 빈번한 메모리 할당 및 해제는 가비지 컬렉션을 유발하여 프레임 드랍이 발생할 수 있다.
- 오브젝트 풀로 가비지 컬렉션 급증으로 인해 발생할 수 있는 밑줄 끊김 현상(Hiccup, GC spike)을 예방할 수 있다.
- 일정한 메모리 사용
- 한 번에 생성할 수 있는 오브젝트의 개수를 제한할 수 있다.
- (반대로, 생성하고 사용하지 않을 경우 메모리 낭비가 되는 단점이 있다.)
📌 오브젝트 풀의 구조와 구현
오브젝트 풀의 기본 구성 요소는 Pool, Pool Manager(관리자), Client(사용자)로 나눌 수 있다.
- Pool
- 미리 생성된 객체를 저장
- 일반적으로
List
,Queue
, 혹은Stack
자료 구조를 사용한다. (아래 예시코드는Stack
사용)
- Pool Manager(관리자)
- Pool에서 객체를 가져오거나 반환하는 역할 담당
- 필요한 경우 새로운 객체를 생성하거나 Pool에 반환
- Client(사용자)
- 오브젝트 풀에 객체를 요청해서 사용 후 반환
🔖 Object Pool
Unity에서 사용하는 기본적인 오브젝트 풀(Object Pool)의 구현 예시이다.
예시 코드 | 오브젝트 풀(Object Pool)
🌞 유니티에서 배포한 코드입니다.
/* 오브젝트 풀 */ public class ObjectPool : MonoBehaviour { [SerializeField] private uint initPoolSize; // 풀(Pool) Size 설정 [SerializeField] private PooledObject objectToPool; private Stack<PooledObject> stack; // 풀링된 오브젝트들을 담는 스택 private void Start() { SetupPool(); // 게임 플레이 중 한 번 실행 } /* 풀 생성 */ private void SetupPool() { stack = new Stack<PooledObject>(); PooledObject instance = null; for (int i = 0; i < initPoolSize; i++) // 위에서 정한 initPoolSize만큼 생성 { instance = Instantiate(objectToPool); instance.Pool = this; instance.gameObject.SetActive(false); // 비활성화 🔴 (준비 단계이기 때문에 비활성 해놓기) stack.Push(instance); } } /* 풀에서 첫 번째 액티브 게임 오브젝트를 반환 */ public PooledObject GetPooledObject() { /* 풀이 비어있으면(=더이상 꺼낼 오브젝트가 없으면), 새로운 PooledObjects를 인스턴스화*/ if (stack.Count == 0) { PooledObject newInstance = Instantiate(objectToPool); newInstance.Pool = this; return newInstance; // 일회성 인스턴스 } /* 그렇지 않으면, 풀에서 다음 요소(인스턴스)를 꺼냄 */ PooledObject nextInstance = stack.Pop(); nextInstance.gameObject.SetActive(true); // 활성화 🔵 return nextInstance; } /* 사용이 끝난 오브젝트를 풀에 반환할 때 호출 */ public void ReturnToPool(PooledObject pooledObject) { stack.Push(pooledObject); pooledObject.gameObject.SetActive(false); // 비활성화 🔴 } }
풀링된 오브젝트(Client)는 ObjectPool.cs을 참조하기 위해 아래 PooledObject 컴포넌트를 가진다.
/* Object Pool의 관리 대상인 오브젝트 */ public class PooledObject : MonoBehaviour { private ObjectPool pool; public ObjectPool Pool { get => pool; set => pool = value; } /* 게임 오브젝트가 비활성화되고 풀로 반환하는 함수 */ public void Release() { pool.ReturnToPool(this); } }
🔖 UnityEngine.Pool (유니티 API)
유니티 2021 버전부터 자체적으로 오브젝트 풀(스택 기반) API을 제공한다. 🔗 Unity Doc
UnityEngine.Pool 은 유니티에서 제공하는 기본 Object Pooling 라이브러리다.
using UnityEngine.Pool
로 사용이 가능하며, 기본적인 인터페이스가 구현되어 있다.
오브젝트 풀을 처음부터 만들 필요가 없어 시간을 단축할 수 있다.
🧩 제공하는 기능
- 오브젝트 생성하여,
Pool
을 채운다. Pool
에서 가져오기Pool
로 반환하기- 풀링 된 오브젝트 파괴하기
- 주로 최대한도에 도달한 경우 사용한다.
예시 코드 | UnityEngine.Pool API 사용
using UnityEngine.Pool; public class RevisedGun : MonoBehaviour { … // Unity 2021 이상 버전에서 사용 가능한 스택 기반 ObjectPool private IObjectPool<RevisedProjectile> objectPool; // 이미 풀에 있는 기존 항목을 반환하려 할 때 예외를 반환 [SerializeField] private bool collectionCheck = true; // 풀의 용량과 최대 크기를 제어하는 추가 옵션 [SerializeField] private int defaultCapacity = 20; [SerializeField] private int maxSize = 100; private void Awake() { objectPool = new ObjectPool<RevisedProjectile>(CreateProjecti le, OnGetFromPool, OnReleaseToPool, OnDestroyPooledObject, collectionCheck, defaultCapacity, maxSize); } // 오브젝트 풀을 채울 항목을 만들 때 호출됨 private RevisedProjectile CreateProjectile() { RevisedProjectile projectileInstance = Instantiate(projectilePrefab); projectileInstance.ObjectPool = objectPool; return projectileInstance; } // 오브젝트 풀로 항목을 반환할 때 호출됨 private void OnReleaseToPool(RevisedProjectile pooledObject) { pooledObject.gameObject.SetActive(false); } // 오브젝트 풀에서 다음 항목을 검색할 때 호출됨 private void OnGetFromPool(RevisedProjectile pooledObject) { pooledObject.gameObject.SetActive(true); } // 풀링된 항목의 최대 개수를 초과할 때 호출됨(풀링된 오브젝트 파괴) private void OnDestroyPooledObject(RevisedProjectile pooledObject) { Destroy(pooledObject.gameObject); } private void FixedUpdate() { … } }
📌 오브젝트 풀의 단점
오브젝트 풀의 문제점으로는 메모리 낭비 가능성이 있다.
- 필요 이상의 객체를 미리 생성하면 메모리가 낭비될 수 있다.
- 사용되지 않는 객체도 메모리를 점유한다.
Thread-Safe 하지 않다.
- 멀티스레드에서 사용하기 위해선 동기작업이 필요하다.
참고
게임 프로그래밍 패턴으로 코딩 스킬 업그레이드
새로운 전자책에서는 잘 알려진 디자인 패턴과 함께 실제 Unity 프로젝트에서 활용할 수 있는 실용적인 예제를 소개합니다.
unity.com
Object pool pattern - Wikipedia
Object pool pattern - Wikipedia
From Wikipedia, the free encyclopedia Software creational design pattern The object pool pattern is a software creational design pattern that uses a set of initialized objects kept ready to use – a "pool" – rather than allocating and destroying them on
en.wikipedia.org
오브젝트 풀링을 사용하여 Unity에서 C# 스크립트 성능 향상하기
오브젝트 풀링을 사용하여 Unity에서 C# 스크립트 성능 향상하기
이 페이지에서는 오브젝트 풀링과 이를 통해 게임 성능을 개선하는 방법에 대해 설명합니다. 여기에는 프로젝트에 Unity의 빌트인 오브젝트 풀링 시스템을 구현하는 방법에 대한 예제가 포함되
unity.com
'👻 Unity' 카테고리의 다른 글
[Unity] 싱글톤 패턴(Singleton Pattern): 오직 하나뿐인 객체 (0) | 2024.11.27 |
---|---|
[Unity] 유니티 설치 실패: Validation Failed 원인 및 해결 방법 (0) | 2024.08.20 |