반응형
오브젝트 풀
게임에서 자주 생성되고 파괴되는 오브젝트들을 미리 생성해두고 재활용하는 디자인 패턴
기본 구현 방법
public class ObjectPool : MonoBehaviour
{
public GameObject prefab; // 풀링할 프리팹
public int poolSize = 20; // 풀 크기
private List<GameObject> pool; // 풀 리스트
void Start()
{
// 풀 초기화
pool = new List<GameObject>();
for (int i = 0; i < poolSize; i++)
{
CreateNewObject();
}
}
// 새 오브젝트 생성
private GameObject CreateNewObject()
{
GameObject obj = Instantiate(prefab);
obj.SetActive(false);
pool.Add(obj);
return obj;
}
// 오브젝트 가져오기
public GameObject GetObject()
{
// 비활성화된 오브젝트 찾기
for (int i = 0; i < pool.Count; i++)
{
if (!pool[i].activeInHierarchy)
{
pool[i].SetActive(true);
return pool[i];
}
}
// 없으면 새로 생성
return CreateNewObject();
}
}
사용방법
// 오브젝트 풀 사용 예시
public class BulletSpawner : MonoBehaviour
{
private ObjectPool bulletPool;
void Start()
{
bulletPool = GetComponent<ObjectPool>();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// 총알 발사
GameObject bullet = bulletPool.GetObject();
bullet.transform.position = transform.position;
}
}
}
핵심개념
1. 기본 원리
- 오브젝트를 미리 생성하여 풀(Pool)에 보관
- 오브젝트가 필요할 때 Instantiate 대신 풀에서 가져옴
- 사용이 끝난 오브젝트는 Destroy 대신 풀로 반환
- 반환된 오브젝트는 다시 재사용
2. 핵심동작
- 초기화: 시작 시 필요한 만큼 오브젝트를 미리 생성
- 대여(Spawn): 풀에서 비활성화된 오브젝트를 찾아 활성화
- 반환(Despawn): 사용이 끝난 오브젝트를 비활성화하여 풀로 반환
- 재활용: 반환된 오브젝트를 다시 사용
사용 목적
- 메모리 효율성 향상
- 성능 최적화 (잦은 생성/파괴 방지)
- 가비지 컬렉션 부하 감소
- 일관된 메모리 사용량 유지
오브젝트 풀 패턴의 장점
1. 성능 향상
- 잦은 Instantiate/Destroy 호출 감소
- 가비지 컬렉션 부하 감소
- 메모리 할당/해제 최소화
2. 메모리관리
- 사전 할당으로 메모리 사용량 예측 가능
- 런타임 중 메모리 단편화 감소
3. 자원 재활용
- 오브젝트 재사용으로 효율성 증가
- 동적 할당 오버헤드 감소
주요 사용 사례
- 총알, 파티클 효과
- 적 캐릭터
- 아이템, 수집품
- UI 요소
- 프로젝타일
사용 사례 예시
총알
public class BulletPool : MonoBehaviour
{
[SerializeField] private GameObject bulletPrefab;
private Queue<GameObject> bullets = new Queue<GameObject>();
private void Start()
{
// 총알 30개 미리 생성
for (int i = 0; i < 30; i++)
{
GameObject bullet = Instantiate(bulletPrefab);
bullet.SetActive(false);
bullets.Enqueue(bullet);
}
}
public GameObject GetBullet()
{
if (bullets.Count > 0)
{
GameObject bullet = bullets.Dequeue();
bullet.SetActive(true);
return bullet;
}
return null;
}
}
파티클
public class ParticlePool : MonoBehaviour
{
private Queue<ParticleSystem> particles = new Queue<ParticleSystem>();
public ParticleSystem GetParticle()
{
ParticleSystem particle = particles.Count > 0 ? particles.Dequeue() : null;
if (particle != null)
{
particle.gameObject.SetActive(true);
particle.Play();
}
return particle;
}
}
적 캐릭터
public class EnemyPool : MonoBehaviour
{
private Queue<Enemy> enemies = new Queue<Enemy>();
public Enemy SpawnEnemy(Vector3 position)
{
Enemy enemy = enemies.Count > 0 ? enemies.Dequeue() : null;
if (enemy != null)
{
enemy.transform.position = position;
enemy.gameObject.SetActive(true);
enemy.ResetEnemy(); // 적 상태 초기화
}
return enemy;
}
}
UI 요소 ( 데미지 텍스트 등 )
public class DamageTextPool : MonoBehaviour
{
private Queue<TextMeshProUGUI> damageTexts = new Queue<TextMeshProUGUI>();
public void ShowDamageText(Vector3 position, int damage)
{
if (damageTexts.Count > 0)
{
var text = damageTexts.Dequeue();
text.text = damage.ToString();
text.transform.position = position;
text.gameObject.SetActive(true);
StartCoroutine(HideText(text, 1f));
}
}
}
결론
1. 주요 사용 이유
- 성능 최적화: Instantiate/Destroy 호출 감소로 성능 향상
- 메모리 관리: 일관된 메모리 사용으로 가비지 컬렉션 부하 감소
- 리소스 효율성: 오브젝트 재사용으로 시스템 자원 절약
2. 적합한 상황
- 자주 생성/파괴되는 오브젝트가 있을 때
- 동시에 많은 오브젝트가 필요할 때
- 실시간 성능이 중요한 게임에서
3. 주의사항
- 초기 메모리 사용량 증가 고려
- 풀 크기의 적절한 설정 필요
- 오브젝트 재사용 시 상태 초기화 관리
오브젝트 풀 패턴은 게임의 성능과 리소스 관리를 최적화하는데
매우 효과적인 디자인 패턴이다
모바일 게임이나 많으 객체를 다루는 뱀서류 같은
게임에서는 필수적인 최적화 도구일 것이다.
반응형
'유니티 > 디자인패턴' 카테고리의 다른 글
[Unity] 유니티 C#) Visitor 패턴 (0) | 2024.12.06 |
---|---|
[Unity] 유니티 C#) Observer 패턴 (0) | 2024.12.05 |
[Unity] 유니티 C#) Singleton 패턴 (0) | 2024.12.03 |
[Unity] 유니티 C#) EventBus 패턴 (0) | 2024.12.03 |
[Unity] 유니티 C#) Command 패턴 (0) | 2024.12.03 |