![[Unity Tip] 3. 오브젝트 풀링(Object Pooling) 1 오브젝트 풀링](https://i0.wp.com/allhoneytip.com/wp-content/uploads/2023/08/Object-Pool-optimized.webp?ssl=1)
오브젝트 풀링이란?
Unity에서 게임을 개발할 때 일명 “소환” 이라는 기능을 구축해야 할 상황이 많이 놓여집니다. 일반적으로는 이럴때 Instantiate 라는 함수를 사용해 게임 오브젝트를 생성하곤 하는데요, 소규모의 게임 프로젝트에서는 괜찮겠지만, 게임의 규모가 커질수록 객체를 생성하는 행위는 게임 성능에 악영향을 미칠 수 있습니다.
그래서 대게 Programming Strategy(전략) 중 하나인 오브젝트 풀링 이라는 기술을 사용해줍니다. 오브젝트 풀링은 미리 생성된 객체들을 관리하여 재활용하는 방식으로, 메모리 사용과 성능을 향상시킬 수 있습니다.
[Unity Tip] 2. Target 겨냥하기 (1-1) 보러가기
예시 코드
우선, ObjectPool 클래스를 생성하여 몬스터들을 담는 스크립트를 작성해줍니다.
using UnityEngine;
using System.Collections.Generic;
public class ObjectPool<T> where T : Component
{
private T prefab;
private Transform parent;
private Queue<T> poolQueue = new Queue<T>();
public ObjectPool(T prefab, int initialSize, Transform parent = null)
{
this.prefab = prefab;
this.parent = parent;
for (int i = 0; i < initialSize; i++)
{
T obj = GameObject.Instantiate(prefab);
obj.gameObject.SetActive(false);
poolQueue.Enqueue(obj);
if (parent != null)
{
obj.transform.parent = parent;
}
}
}
public T GetObject()
{
if (poolQueue.Count > 0)
{
T obj = poolQueue.Dequeue();
obj.gameObject.SetActive(true);
return obj;
}
else
{
T obj = GameObject.Instantiate(prefab);
if (parent != null)
{
obj.transform.parent = parent;
}
return obj;
}
}
public void ReturnObject(T obj)
{
obj.gameObject.SetActive(false);
poolQueue.Enqueue(obj);
}
}
- 제네릭 클래스로, 특정 컴포넌트 타입(
T
)의 오브젝트를 관리하는 오브젝트 풀을 구현합니다.
- 초기 크기(initialSize)를 가진 풀을 생성하고, 오브젝트가 필요할 때마다 풀에서 가져오거나 비활성화하여 다시 풀에 반환합니다.
다음으로, SpawnManager 스크립트를 생성하여 몬스터 생성을 관리해 줍니다.
using UnityEngine;
public class SpawnManager : MonoBehaviour
{
public GameObject monsterPrefab;
public int initialPoolSize = 10;
public float spawnInterval = 1f;
public float spawnRadius = 5f;
private ObjectPool<MonsterController> monsterPool;
private Transform spawnPoint;
private void Start()
{
spawnPoint = transform;
monsterPool = new ObjectPool<MonsterController>(monsterPrefab.GetComponent<MonsterController>(), initialPoolSize, transform);
InvokeRepeating(nameof(SpawnMonster), 0f, spawnInterval);
}
private void SpawnMonster()
{
Vector3 randomOffset = Random.insideUnitCircle * spawnRadius;
Vector3 spawnPosition = spawnPoint.position + randomOffset;
MonsterController monster = monsterPool.GetObject();
monster.transform.position = spawnPosition;
monster.Respawn();
}
public void ReturnObject(MonsterController monster)
{
monsterPool.ReturnObject(monster);
}
}
- 몬스터 프리팹과 스폰 간격, 스폰 위치 등을 설정하여 일정 간격마다 몬스터를 스폰합니다.
- 몬스터를 생성할 때
ObjectPool
을 사용하여 몬스터를 관리합니다.
마지막으로, MonsterController 스크립트를 작성하여 몬스터를 제어해 줍니다!
using UnityEngine;
public class MonsterController : MonoBehaviour
{
public float maxHealth = 100f;
private float currentHealth;
private void Start()
{
currentHealth = maxHealth;
}
public void TakeDamage(float damage)
{
currentHealth -= damage;
if (currentHealth <= 0f)
{
Die();
}
}
private void Die()
{
gameObject.SetActive(false);
SpawnManager spawnManager = FindObjectOfType<SpawnManager>();
if (spawnManager != null)
{
spawnManager.ReturnObject(this);
}
}
public void Respawn()
{
gameObject.SetActive(true);
currentHealth = maxHealth;
}
}
- 몬스터의 체력을 다루며, 일정 체력 이하로 떨어지면 몬스터를 비활성화하여 사망 처리합니다.
다시 말해, 몬스터 사망 시 SpawnManager 스크립트 내 InvokeRepeating을 통해 SpawnMonster 함수가 지속적으로 실행이 되고, 해당 함수 내 monsterPool.GetObject() 호출을 통해 ObjectPool 스크립트의 GetObject() 함수를 호출해주게 됩니다.
GetObject() 함수를 통해 큐에 있던 몬스터 오브젝트를 반환해주며 setActive를 true로 변경해 줍니다. 또한 몬스터 사망시에는 MonsterController 스크립트 내, Die() 함수를 통해 오브젝트 풀에 몬스터 오브젝트를 다시 넣어줘서 재사용 가능하게끔 만들어 줍니다.
답글 남기기